Getting started with the CRM 2011 Windows Store app sample


UPDATE (18APR2013): Updated AuthenticateAsync() extension method to handle both IFD and CRM Online authentication.  Now, the code in HelloCRM will work regardless of whether you point it to an IFD or CRM Online Organization Service.  All you have to do is pass in the appropriate username/password combo to AuthenticateAsync().  Quick link to updated code: http://sdrv.ms/Qy0Wcv.

UPDATE (12MAR2013): Found another issue with my helper extension methods around when I was detaching the event handler.  Uploaded a zip file with the improved helper methods.

UPDATE: There was a bug in my extension methods.  I wasn’t detaching the event handlers after the event had been handled.  This caused issues with subsequent calls to the Async extensions methods.  I’ve fixed the code to detach the event handlers appropriately.

I’ve blogged about a hackish, but workable approach to building an Windows Store app here and here.  However, as I mentioned in the post, if you like it use it.  If not wait until there’s an official SDK sample.  Well, in early November, the CRM time published the official SDK sample:

http://blogs.msdn.com/b/crm/archive/2012/11/02/building-clients-for-windows-phone-and-windows-8-rt.aspx

The feedback I’ve gotten from a few folks who’ve looked at the official sample is:

  • “It’s not exactly the easiest sample to follow.  Can you give me a hello world example?”
  • “I can’t use crmsvcutil.exe generated code with the sample.”
  • “I have to use Event-based Asynchronous Pattern (EAP)?  It’s Windows 8!  Everyone expects async / await capable APIs.”

The goal of this post is to address these common responses with:

  • A simplified hello world example to get you started
  • How to use crmsvcutil.exe generated entities so you have early bound / strongly typed / data binding friendly classes
  • Starter extension method examples which wrap the EAP nature of the sample API and give you async / await friendly methods

 

 

You can grab the hello world example from the video here:

http://sdrv.ms/Qy0Wcv

In the video, I make reference to Erik Pool’s wonderful tool to control what gets generated from crmsvcutil.exe:

http://erikpool.blogspot.com/2011/03/filtering-generated-entities-with.html

The inspiration for the Extension methods comes from this Stack Overflow post:

http://stackoverflow.com/questions/12853445/convert-event-based-pattern-to-async-ctp-pattern

I blogged about using LINQPad to create FetchXml here:

http://blogs.msdn.com/b/devkeydet/archive/2012/04/22/getting-fetchxml-from-linqpad.aspx

@devkeydet

Comments (7)

  1. webresource giving error

    window.location.href.indexOf("WebResource.ashx") == -1 && window.external.notify("{'source':'LOGGED_IN'}");

    this line giving me error for  

    Webpage error details

    User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)

    Timestamp: Mon, 4 Feb 2013 15:08:19 UTC

    Message: Invalid character

    Line: 1

    Char: 1

    Code: 0

    URI: file:///C:/Users/532802/ClientGlobalContext.js.aspx

    Message: Object doesn't support this property or method

    Line: 199

    Char: 13

    Code: 0

    URI: file:///C:/Users/532802/Desktop/webresource.html

  2. marcsc says:

    You seem to be referencing the sample form these posts:

    blogs.msdn.com/…/updated-sample-crm-2011-windows-store-app-odata-helper.aspx

    blogs.msdn.com/…/using-the-crm-2011-odata-service-from-a-metro-style-app.aspx

    I wrote both of these when there wasn't an official SDK sample.  These are "AS IS" and I don't currently have the free time to debug the old sample.  You'd be better off using the official SDK sample I blog about in this post.  However, if you still want to use the old approach, the good news is that it's code.  Modify it to continue working.

  3. Darrel says:

    ExtensionMethod class

    public static Task<ObservableCollection<T>> RetrieveMultipleAsync<T>(this OrganizationServiceProxy organizationServiceProxy, QueryBase Queue)

           {

               var tcs = new TaskCompletionSource<ObservableCollection<T>>();

               organizationServiceProxy.RetrieveMultipleCompleted += (o, args) =>

               {

                   if (args.Error != null) tcs.TrySetException(args.Error);

                   else if (args.Cancelled) tcs.TrySetCanceled();

                   else

                   {

                       var observableCollection = new ObservableCollection<T>();

                       var entitycount = args.Result.Entities.Count;

                       for (int i = 0; i < entitycount; i++)

                       {

                           observableCollection.Add(args.Result[i].ToEntity<T>()); // I get an error here saying "the type "T" cannot be used as type parameter 'T' in the generic type or method Microsoft.Xrm.SDK.Entity.toEntity<T>()". there is no boxing conversion or type parameter conversion from T to Microsoft.Xrm.Sdk.entity"

                       }

                       tcs.TrySetResult(observableCollection);

                   }

               };

               organizationServiceProxy.RetrieveMultiple(Queue);

               return tcs.Task;

           }

    Kindly help, Its an urgent requirement.

  4. marcsc says:

    @Darrel – The error you are getting is expected.  RetrieveMultipleAsync<T>() requires that T is a class which was generated using crmsvcutil.exe.  From the error message, it sounds like you are trying to use Microsoft.Xrm.Sdk.entity for T which is not possible with this method.  There is a RetrieveMultipleAsync() that's not generic which you should use instead.  This is source code and intended help you get started.  Since it's source code, you can look at it and make any adjustments necessary.  I blog in my free time mostly and can't always respond to "urgent" issues with code samples.  They are provided AS-IS.

  5. Jonathan says:

    Hi, thanks alot for the video…it really helps newbies like myself, this question is with regards to extension methods….could you post a code snippet of an update async method….. it would be really helpful if you could share it with us.

    Thanks again for the hello world tutorial…

  6. Jonathan says:

    Here's my Code:

    public static Task<Guid> UpdateAsync(this OrganizationServiceProxy organizationServiceProxy, Entity entity)

           {

               var tcs = new TaskCompletionSource<Guid>();

               organizationServiceProxy.UpdateCompleted += (o, args) =>

               {

                   if (args.Error != null) tcs.TrySetException(args.Error);

                   else if (args.Cancelled) tcs.TrySetCanceled();

                   else tcs.TrySetResult(args.Result);   // Am Getting an Error here:

    'System.ComponentModel.AsyncCompletedEventArgs' does not contain a definition for 'Result' and no extension method 'Result' accepting a first argument of type 'System.ComponentModel.AsyncCompletedEventArgs' could be found (are you missing a using directive or an assembly reference?)

               };

               organizationServiceProxy.Update(entity);

               return tcs.Task;

           }

    your help would be highly appreciated

  7. devkeydet says:

    Jonathan,

    Sorry for the slow response.  Apparently it doesn't like the crmsvcutil.exe generated DataContractAttribute on the Account class which looks like:

    [System.Runtime.Serialization.DataContractAttribute()]

    If you look at the base Entity class, it has:

    [System.Runtime.Serialization.DataContractAttribute(Name = "Entity", Namespace = Microsoft.Xrm.Sdk.XmlNamespaces.V5.Contracts)]

    Replace the top one with the bottom one and it should work.