The Microsoft Dynamics CRM Blog
News and views from the Microsoft Dynamics CRM Team

Building clients for Windows Phone and Windows 8 RT

Building clients for Windows Phone and Windows 8 RT

  • Comments 10

The Microsoft.Xrm.Sdk.dll library provided as part of the Dynamics CRM 2011 SDK makes it easy to write  .NET applications that target the desktop. This library has dependencies on .NET 4.0 and Windows Identity Foundation (WIF), neither of which are available for Windows Phone and Windows 8 RT platforms. Although the WS-Trust protocol used by Dynamics CRM 2011 for authentication is fairly well defined and several folks have built implementations for other languages/platforms, we want to make it easy for you to build amazing applications on these platforms , so a reference implementation of the CRM SDK for these platforms is provided here. Unlike the desktop version, where we only provided you with the binary assembly, we have provided the complete source code, so you should be able to make changes to fit your specific needs.  Please note that this works for Dynamics CRM Online deployments, both Office 365 and Windows Live ID, and for Internet Facing Deployments (IFD). It does not work for Dynamics CRM on-premises deployments using Active Directory authentication.

This code is provided “as is”, so you are responsible for making any fixes.

The rest of this post describes how to use the code to authenticate and send web service requests.

Authenticating to the CRM Web Services

Use ServiceConfigurationFactory to construct a DiscoveryServiceConfiguration or an OrganizationServiceConfiguration object. These classes load the relevant metadata and raise one of these events:

  • MetadataLoaded event if the service metadata has been loaded successfully
  • MetadataLoadFailure for other failure cases, such as when the endpoint is not reachable

Once the metadata has been loaded, you can call the Authenticate method. On completion, the Authenticate methods raise the SignInComplete event. The SignOnCompletedEventArgs object on the event callback contains the returned token in the Result property on successful authentication, and contains a non-null exception in the Error property in the case of failed authentication. You can use the returned token to call CRM web service methods.

Windlows Live ID authentication requires device authentication to be performed first, in which case the authentication flow is AuthenticateDevice -> DeviceSigninComplete event -> Authenticate -> SignInComplete event, which can be achieved as shown below:

  1. Attach to the DeviceSigninComplete event and do the following in the event handler:
    1. Handle any error in device authentication by examining the SignOnCompletedEventArgs.Error property. If there is no error, continue with the following
    2. Attach to the SignInComplete event for the user authentication. In the handler, handle any error/read the returned token
    3. Call Authenticate(ClientCredentials clientCredentials, RequestSecurityTokenResponse deviceSecurityToken) passing in the user credentials and the returned token response from device authentication
  2. Call AuthenticateDevice passing in the device credentials to trigger the authentication flow. The DeviceSigninComplete event triggers the user authentication (achieved by step 1)

Calling the CRM Web Services

  1. If no cached token available, authenticate as shown above, and cache the returned token.
  2. Instantiate either the DiscoveryServiceProxy or the OrganizationServiceProxy object as needed.
  3. Set the SecurityTokenReponse property on the proxy object to the cached token.
  4. Attach to the corresponding completion event for the method to be called. For example, use CreateCompleted for the Create method, ExecuteCompleted for the Execute method.
  5. Call the web service method on the DiscoveryServiceProxy or OrganizationServiceProxy objects.
  • Thank you for this article and sample code.

    Question: when developing an application which needs to retrieve data with multiple separate CRM SDK queries, how this can be done in this asynchronous development model? For example, if I have a single button on a WinRt application which needs to trigger two queries: first query a list of some entities from CRM and then trigger another query for each of the entities returned by the first query. Doing these in nested methods (events) does not seem to return the data at all for the second query (at least per my quick test on the sample).

    Thanks,

    Jose

  • Hi Jose,

    How are you doing the second query? I'm assuming it's in a loop?

    The problem with the provided sdk is that the asynchronous pattern they used is Event-based. So it's not straightforward to chain the calls. And I noticed with WinRt is that it only allow two connections at a time. It's possible some of the connection were overlapping.

    It would have been simpler if the sdk is using Task-based pattern.

  • Yes, I am doing the second query in a loop. Basically in the first query, I get GUIDs of one entity rows and then loop through those and do second query based on the GUIDs. Naturally it is possible to store the results (GUIDs) of the first query to a list and then do a second query based on the list but that is not the final solution that I am looking for as I need to do more than the second query (there will be third and fourth etc.).

    So yes, it is quite challenging to do this type of solutions when pattern in the SDK is Event-based. I started wondering that is there a reason for this? I mean as the programming pattern for developing windows store apps is anyway asynchronous which means that the worker thread is anyways working in the background and the UI-thread is called only when something is ready to be rendered to the UI. So to go back to the basics, what are the reasons that the client side programming must be done this way?

    Thanks,

    Jose

  • We have a internet facing CRM instance which we are trying to connect using the sample code given. In our code CreateConfiguration of ServiceConfigurationFactory is unable to load metadata, so we are not able to authenticate to that CRM. Looking inside the Xrm.sdk we have found that in WSTrustPolicyImporter class (file:WSTrustPolicy.cs), we are getting WSTrust2005 instead of WSTrust13, and there it is mentioned that it supports 13 only. So it was unable to fetch TokenPolicy. Can anybody help us regarding what we need to change in the CRM server instance and/or client to get that problem solved?

  • Anyone have this working with a CRM Live org?  All I receive is authentication failure.  How we retrieve the deviceid/password through a WinRT app?

  • @s1rf: had the same issue: in this link blog.abodit.com/.../crmsvcutil-exe-with-microsoft-dynamics-crm-2011-online-problem , there was discussed, how to generate a deviceid/pw. I provided deviceid and pw to the Deviceregistration.exe and got back a slightly diffrent (!) deviceid. Using this deviceid, the connect succeeded.

    So, basically , user the deviceregistration utility to generate id and pw and put it in the code. (additionally, i chose the crm online link in the code (only slightly diffrent from the office365 link...)

    hop this helps,

     Christian

  • Thanks @Christian for the tip.  Though I'm still a little confused.  If I distributed the app (or put in the win appstore), how do I get the users device registered from my WinRT app?

  • @s1rf: Sorry for the late answer. You are absolutely right. I am going to investigate this problem now and i will share my experiences ;-) . I had issues to understand connecting to an ifd scenario, which is working right now...

    @hp_mobility_win8: in the samplecode, ifd adressing is simply not implemented. The AuthenticationType in the CurrentEnvironment.DiscoveryServiceConfiguration.ServiceEndpointMetadata comes as Federation. I simply added a case in the switch handling this:

                   case (AuthenticationProviderType.OnlineFederation):

                       AuthenticateOnlineFederation();

                       break;

                   case (AuthenticationProviderType.Federation):

                       CurrentEnvironment.DiscoveryServiceConfiguration.Authenticate(CurrentEnvironment.CreateLiveIdUserCredentials());

                       break;

    (buttonSignIn_Click in SignIn.Xaml.cs) and was able to connect to our ifd system.

    Hope this helps, Christian

  • Thanks so much Christian, I'll be checking out the update soon.

  • any update on this one?

Page 1 of 1 (10 items)
Leave a Comment
  • Please add 1 and 4 and type the answer here:
  • Post