Showing posts with label cross-platform. Show all posts
Showing posts with label cross-platform. Show all posts

Thursday, April 13, 2017

Sample SOAP payload for a SharePoint Remote Event Receiver

This post is mostly about showing what an actual Remote Event Receiver message looks like but there are some of my musings too because if there's something I love more than coding it is ranting about minor annoyances with the tools we use for doing it. If you can't wait to see the actual sample - go straight ahead, it's waiting for you at the end. For the most patient ones - let the rant begin!

First, a bit of context - I've joined new team working on a super complex project and as a result they are not letting me anywhere near the actual code for a second month now. What do they have me do, then? What could be the most inconsequential thing for a noob to do that would still have them learn about the solution? You guessed right - unit tests! So I want to test a Remote Event Receiver (RER for short) and I though, well, surely there must be a sample SOAP message sent by a RER somewhere around teh interwebz. Disappointingly, if there is such a thing it is very well hidden as I couldn't find it and had to generate my own. It wasn't as simple as one might think so I'm sharing the fruit of this labour with the world.

Now is the time to rant a bit about the frustrations regarding SharePoint development. I've ranted before about how hard it is to find anything meaningful online because of the ubiquity of posts explaining trivial stuff. Seriously, who needs a million how-tos about adding a RER to an app? You just right-click on the project in Visual Studio and follow the wizard. One thing I haven't moaned about before though is the inept way Microsoft is presenting SharePoint app development. And no, I'm not even referring to the ham-fisted rebranding from "apps" to "add-ins", which left the community calling them "apps" while MS insist that they are "add-ins", in the same way that MS insisted for years that JavaScript is actually called EcmaScript.


What is SharePoint app development anyway?

If you try to teach yourself SharePoint 2013/2016 through online resources, or even if you attend a course or read a book they'll have you believe that before you even write a hello world app you need to understand about SharePoint-hosted vs Provider hosted, you need to know what's the app web and host web, the remote web app, etc. and before you even start coding you need to configure your farm for apps, which is decidedly non-trivial.

I'd say screw all this and don't confuse people with the complexities of deployed apps from day one - it's needlessly obscure and fails to drive home the main point of the SP 2013/2016 app architecture: from now on, you won't be writing applications that get deployed into SharePoint, you'll be building ASP.NET apps that talk to SharePoint through the client library.
That's what Microsoft doesn't want you to know and maybe even fail to admit it to themselves but seriously, does anyone actually build apps to be deployed through an app catalog? Almost all projects I've worked on lately involve writing code in an ASP.NET application that talks to SharePoint through the CSOM. Yeah, I get it, MS built all this app catalog infrastructure and now want to shove it down our throats so they keep talking about provider hosted and app web and whatnot when you just want to connect to SharePoint and update some files.

So, if there is a beginner SharePoint developer reading this - fear not, it's not as complicated as MS make it sound. Nowhere is this more obvious than when we bring Remote Event Receivers (RER) into the picture. If you go by MS sources alone you'll start pulling your hair in despair, expecting weeks of work just to get the damn thing to work - now you don't just have the usual moving parts and security config, you also have a service that needs yet another way to obtain a SharePoint context! Well, guess what - you don't need any of that - you just create your service that implements the correct contract, call a few lines of CSOM code to register your services as a RER and you're good to go; no apps, no app-only policy configuration, no nothing. Now is the time to give a big shout out to Dan Budimir, who went against the grain at MS and wrote a guide about this very thing:
https://blogs.msdn.microsoft.com/boodablog/2015/01/12/i-thought-i-needed-a-sharepoint-provider-hosted-app-for-that-part-1/


How do we capture the SOAP message?

When I came to be in need of a recorded SOAP payload from a RER my first thought was - hey, we already have this functionality in IIS through Failed Request Tracing, which can be used to record all traffic, including requests that didn't actually fail. However, it has a size limit and for most RER request bodies it actually cuts the ending. Therefore, Fiddler had to come to the rescue - here is the whole process if you want to capture some requests yourself:
If all this sounds too complicated (which it is) - just make use of the few that I prepared, you should be able to adapt them if they don't cover the event you need.
Below you'll find the full text dumps for ItemDeleted (the smallest one) and ItemUpdated and here are links for two more events:
ItemAdded
ItemFileMoved (that's the event that gets fired when you rename a file)


ItemDeleted

<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <ProcessOneWayEvent xmlns="http://schemas.microsoft.com/sharepoint/remoteapp/">
         <properties xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <AppEventProperties i:nil="true" />
            <ContextToken />
            <CorrelationId>5bccd79d-32db-e06a-0000-077828386b67</CorrelationId>
            <CultureLCID>1033</CultureLCID>
            <EntityInstanceEventProperties i:nil="true" />
            <ErrorCode />
            <ErrorMessage />
            <EventType>ItemDeleted</EventType>
            <ItemEventProperties>
               <AfterProperties xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
               <AfterUrl i:nil="true" />
               <BeforeProperties xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
               <BeforeUrl>Docs/test11.txt</BeforeUrl>
               <CurrentUserId>22</CurrentUserId>
               <ExternalNotificationMessage i:nil="true" />
               <IsBackgroundSave>false</IsBackgroundSave>
               <ListId>6980e5dd-d847-4667-8792-1e2741d6cf18</ListId>
               <ListItemId>7</ListItemId>
               <ListTitle>Docs</ListTitle>
               <UserDisplayName>Kiryazov, S. (Stefan)</UserDisplayName>
               <UserLoginName>i:0#.w|europe\d-hy32co</UserLoginName>
               <Versionless>false</Versionless>
               <WebUrl>http://sharepoint.server/sites/sitecolurl</WebUrl>
            </ItemEventProperties>
            <ListEventProperties i:nil="true" />
            <SecurityEventProperties i:nil="true" />
            <UICultureLCID>1033</UICultureLCID>
            <WebEventProperties i:nil="true" />
         </properties>
      </ProcessOneWayEvent>
   </s:Body>
</s:Envelope>

ItemUpdated

<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <ProcessOneWayEvent xmlns="http://schemas.microsoft.com/sharepoint/remoteapp/">
      <properties xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <AppEventProperties i:nil="true" />
        <ContextToken />
        <CorrelationId>00000000-0000-0000-0000-000000000000</CorrelationId>
        <CultureLCID>1033</CultureLCID>
        <EntityInstanceEventProperties i:nil="true" />
        <ErrorCode />
        <ErrorMessage />
        <EventType>ItemUpdated</EventType>
        <ItemEventProperties>
          <AfterProperties xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
            <a:KeyValueOfstringanyType>
              <a:Key>vti_folderitemcount</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">0</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_nexttolasttimemodified</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:dateTime">2017-02-01T08:30:41</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_candeleteversion</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">true</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_foldersubfolderitemcount</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">0</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_canmaybeedit</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">true</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>ContentTypeId</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">0x010100AE33CE7DE32F484490EEC317F89BE311</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_sourcecontrolcookie</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">fp_internal</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_filesize</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">1376</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_modifiedby</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">i:0#.w|domain\username</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_setuppathversion</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">15</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_level</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">1</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_timecreated</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:dateTime">2017-02-01T08:30:41</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_charset</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">utf-8</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_parserversion</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">15.0.0.4867</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_sourcecontrolversion</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">V1.0</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_author</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">i:0#.w|domain\username</a:Value>
            </a:KeyValueOfstringanyType>
          </AfterProperties>
          <AfterUrl>Docs/soap-list1.xml</AfterUrl>
          <BeforeProperties xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
            <a:KeyValueOfstringanyType>
              <a:Key>vti_metadatanextbsn</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">100</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_backgroundsave</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">0</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_replid</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">rid:{2824DA8B-7E05-4687-A6D3-E5293D4439FC}</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_level</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">1</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>ContentTypeId</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">0x010100AE33CE7DE32F484490EEC317F89BE311</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_setuppathversion</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">15</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_rtag</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">rt:2824DA8B-7E05-4687-A6D3-E5293D4439FC@00000000002</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_sourcecontrolversion</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">V1.0</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_sourcecontrolcookie</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">fp_internal</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_filesize</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">1376</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_modifiedby</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">i:0#.w|domain\username</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_metainfoversion</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">2</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_internalversion</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">513</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_nextbsn</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">162</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_parserversion</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">15.0.0.4867</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_docstoreversion</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">2</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_author</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">i:0#.w|domain\username</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_foldersubfolderitemcount</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">0</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_contentversionisdirty</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">false</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_timecreated</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:dateTime">2017-02-01T08:30:41</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_contenttag</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">{2824DA8B-7E05-4687-A6D3-E5293D4439FC},2,2</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_docstoretype</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">0</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_canmaybeedit</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">true</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_charset</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">utf-8</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_folderitemcount</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">0</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_timelastmodified</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:dateTime">2017-02-01T08:55:24</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_parentid</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">{733E0BCD-E0B4-45DA-8492-FDE35C98DD22}</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_candeleteversion</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">true</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_nexttolasttimemodified</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:dateTime">2017-02-01T08:30:41</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_contentversion</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">2</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_etag</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string">"{2824DA8B-7E05-4687-A6D3-E5293D4439FC},2"</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_timelastwritten</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:dateTime">2017-02-01T08:55:24</a:Value>
            </a:KeyValueOfstringanyType>
            <a:KeyValueOfstringanyType>
              <a:Key>vti_streamschema</a:Key>
              <a:Value xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:int">66</a:Value>
            </a:KeyValueOfstringanyType>
          </BeforeProperties>
          <BeforeUrl>Docs/soap-list1.xml</BeforeUrl>
          <CurrentUserId>22</CurrentUserId>
          <ExternalNotificationMessage i:nil="true" />
          <IsBackgroundSave>false</IsBackgroundSave>
          <ListId>6980e5dd-d847-4667-8792-1e2741d6cf18</ListId>
          <ListItemId>2</ListItemId>
          <ListTitle>Docs</ListTitle>
          <UserDisplayName>Kiryazov, S. (Stefan)</UserDisplayName>
          <UserLoginName>i:0#.w|europe\d-hy32co</UserLoginName>
          <Versionless>false</Versionless>
          <WebUrl>http://sharepoint.server/sites/ipp-content-stef</WebUrl>
        </ItemEventProperties>
        <ListEventProperties i:nil="true" />
        <SecurityEventProperties i:nil="true" />
        <UICultureLCID>1033</UICultureLCID>
        <WebEventProperties i:nil="true" />
      </properties>
    </ProcessOneWayEvent>
  </s:Body>
</s:Envelope>


Wednesday, September 28, 2011

.NET is more open than Java

There has always been this stereotype that Microsoft are sworn enemies of open source and Java is uber cross-platform. Well, guess what, that's not true and the proof came in April 2010. I know that this is about a century ago in software years but for some reason the news have gone past me and I'd hate to not comment on that - be it regretably late.

The story goes as follows - after acquiring Sun (and the Java technology along with it), Oracle decided to sue Google over their use of Java on the Android OS (source), basically redefining 'cross-platform' to mean 'running on any platform that Oracle can make money out of'. The fact that Java had a chance to become the de facto universall development environment for mobile devices doesn't matter.

In the same time Microsoft have this thing called Community Promise, which basically means that they are OK with you implementing a .NET environment on any platoform, and more specifally - it means that they won't pull the same stunt about .NET on Android (source, and yeah, .NET development on Android is possible - http://android.xamarin.com/ ).

Now let's get in the time machine and travel back to present day. It's already October 2011 and in the meantime Android has become the dominant OS for smartphones, and Novell have been acquired by Attachmate and along with it - the Mono and Mono for Android team (Ximian, the company that originally developed Mono was acquired by Novell), followed immediately by Attachmate dumping the Mono and MonoDroid teams - a truly disturbing development for the .NET and mobile development communities. However, a large part of the team that originally created Mono now formed Xamarin - a company that is committed to supporting and advancing this family of products, and they have reached an agreement with Attachmate to be the official stewards of these projects.

So, Mono, MonoTouch and Mono for Android, after changing hands three times are now once again in the hands of a small, dedicated team, which is of course very promising. We'll only need to see who will get to buy Xamarin next...

I really hope for one thing, though - that it's not going to be Microsoft or Google, or for that matter - any other major player in the smartphone game, as this will lead to Apple immediately blocking MonoTouch on iOS. For the ones unfamiliar with MonoTouch - this is a product that lets you compile .NET applications for iOS, and with HTML5's future being uncertain before 2022 - that's pretty much the only way to run anything that was not orignially written on Objective C on the iPhone and other iOS devices. Now MonoTouch is not a true .NET implementation - it's not CLR, it doesn't JIT and execute intermediate language code - it just compiles .NET to native code.

There were times that the future of MonoTouch was quite murky - there was the infamous point 3.3.1 in the Apple developer agreement that stipulated that iPhone apps must be originally developed in Objective C, i.e. the trick that MonoTouch does was officially banned. But then the ailing Jobbs was apparently struck by a dose of benevolence and decided to let MonoTouch do its thing.

The implications of both developments - now you can develop in .NET on every major mobile platform! Of course it's not as easy as it sounds - as Miguel de Icaza (the mastermind behind Mono) points out himself, you can only really reuse the business logic, you'll need to implement the front-end differently for every platform. Still, you'll do it with the same tools, and will follow roughly the same practiceses.

The topic of cross-platform mobile development with .NET is one that has captured my interest and I will be posting more about it in the future, so if there's anything that you are particularly interested in, or have something interesting to share please make full use of the comments.