Connecting to CRM 2013 Online SOAP and OData endpoint through Windows 8 App.

In this post we will see how to connect to CRM 2013 Online through a Windows 8 App.

Steps:

Create a new windows store project in Visual Studio.

We need Windows Azure Authentication Library for Windows Store Beta for our app.

To install it, run the following command int Package Manager Console

PM> Install-Package Microsoft.Preview.WindowsAzure.ActiveDirectory.Authentication

The following Assemblies will be added to the project

Next step is to register the app.

Sign in to Graph Explorer using the system account used to access Microsoft Dynamics CRM Online.

https://graphexplorer.cloudapp.net/

Select Add Application Permission option there

Specify Microsoft.CRM in the service already has been registered drop down box.

For Client App Url, use the the following line of code in the windows 8 app to get the redirectUrl.

// Obtain the redirect URL for the app. This is only needed for app registration.

string redirectUrl = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();

 

 

Copy App Url and Client ID value from the Application Permission Creation Summary Page. We will use those values in our windows 8 store app.

The sample code (uses the code found in SDK)

 

public sealed partial class MainPage : Page

{

private static AuthenticationContext _authenticationContext;

private const string _clientID = "71d5ab90-5e85-4352-80c1-0e2dd5849395";

public const string CrmServiceUrl = "https://xxx.crm5.dynamics.com/";

private const string _oauthUrl = "https://login.windows.net/common/wsfed";

 

public MainPage()

{

this.InitializeComponent();

}

 

private void Page_Loaded(object sender, RoutedEventArgs e)

{

Initialize();

}

 // <summary>

/// Perform any required app initialization.

/// This is where authentication with Active Directory is performed.

public static async void Initialize()

{

// Obtain the redirect URL for the app. This is only needed for app registration.

string redirectUrl = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();

 

// Obtain an authentication token to access the web service.

_authenticationContext = new AuthenticationContext(_oauthUrl, false);

// AuthenticationResult result = await _authenticationContext.AcquireTokenAsync("Microsoft.CRM", _clientID);

 

AuthenticationResult result = await _authenticationContext.AcquireTokenAsync("Microsoft.CRM", _clientID,redirectUrl,string.Empty,string.Empty);

 

// Verify that an access token was successfully acquired.

if (AuthenticationStatus.Succeeded != result.Status)

{

if (result.Error == "authentication_failed")

{

// Clear the token cache and try again.

(AuthenticationContext.TokenCache as DefaultTokenCache).Clear();

_authenticationContext = new AuthenticationContext(_oauthUrl, false);

result = await _authenticationContext.AcquireTokenAsync("Microsoft.CRM", _clientID);

}

else

{

DisplayErrorWhenAcquireTokenFails(result);

}

}

 

// Soap Call

RetrieveMultiple(result.AccessToken, new string[] { "firstname", "lastname" }, "contact");

// OData Call

Retrieve(result.AccessToken, new string[] { "FirstName", "LastName" }, "Contact");

/// <summary>

/// Retrieve entity record data from the organization web service.

/// </summary>

/// <param name="accessToken">The web service authentication access token.</param>

/// <param name="Columns">The entity attributes to retrieve.</param>

/// <param name="entity">The target entity for which the data should be retreived.</param>

/// <returns>Response from the web service.</returns>

/// <remarks>Builds a SOAP HTTP request using passed parameters and sends the request to the server.</remarks>

public static async void RetrieveMultiple(string accessToken, string[] Columns, string entity)

{

// Build a list of entity attributes to retrieve as a string.

string columnsSet = string.Empty;

foreach (string Column in Columns)

{

columnsSet += "<b:string>" + Column + "</b:string>";

}

 

// Default SOAP envelope string. This XML code was obtained using the SOAPLogger tool.

string xmlSOAP =

@"<s:Envelope xmlns:s='https://schemas.xmlsoap.org/soap/envelope/'>

<s:Body>

<RetrieveMultiple xmlns='https://schemas.microsoft.com/xrm/2011/Contracts/Services' xmlns:i='https://www.w3.org/2001/XMLSchema-instance'>

<query i:type='a:QueryExpression' xmlns:a='https://schemas.microsoft.com/xrm/2011/Contracts'><a:ColumnSet>

<a:AllColumns>false</a:AllColumns><a:Columns xmlns:b='https://schemas.microsoft.com/2003/10/Serialization/Arrays'>" + columnsSet +

@"</a:Columns></a:ColumnSet><a:Criteria><a:Conditions /><a:FilterOperator>And</a:FilterOperator><a:Filters /></a:Criteria>

<a:Distinct>false</a:Distinct><a:EntityName>" + entity + @"</a:EntityName><a:LinkEntities /><a:Orders />

<a:PageInfo><a:Count>0</a:Count><a:PageNumber>0</a:PageNumber><a:PagingCookie i:nil='true' />

<a:ReturnTotalRecordCount>false</a:ReturnTotalRecordCount>

</a:PageInfo><a:NoLock>false</a:NoLock></query>

</RetrieveMultiple>

</s:Body>

</s:Envelope>";

 

// The URL for the SOAP endpoint of the organization web service.

string url = "https://xxx.crm5.dynamics.com/XRMServices/2011/Organization.svc/web";

 

// Use the RetrieveMultiple CRM message as the SOAP action.

string SOAPAction = "https://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/RetrieveMultiple";

 

// Create a new HTTP request.

HttpClient httpClient = new HttpClient();

 

// Set the HTTP authorization header using the access token.

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

 

// Finish setting up the HTTP request.

HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, url);

req.Headers.Add("SOAPAction", SOAPAction);

req.Method = HttpMethod.Post;

req.Content = new StringContent(xmlSOAP);

req.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("text/xml; charset=utf-8");

 

// Send the request asychronously and wait for the response.

HttpResponseMessage response;

response = await httpClient.SendAsync(req);

var responseBodyAsText = await response.Content.ReadAsStringAsync();

  

}

 

public static async void Retrieve(string accessToken, string[] Columns, string entity)

{

// Build a list of entity attributes to retrieve as a string.

string columnsSet = "";

foreach (string Column in Columns)

{

columnsSet += "," + Column;

}

 

// The URL for the OData organization web service.

string url = "https://xxx.crm5.dynamics.com/XRMServices/2011/OrganizationData.svc/" + entity + "?$select=" + columnsSet.Remove(0, 1) + "";

 

// Build and send the HTTP request.

HttpClient httpClient = new HttpClient();

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, url);

req.Method = HttpMethod.Get;

 

// Wait for the web service response.

HttpResponseMessage response;

response = await httpClient.SendAsync(req);

var responseBodyAsText = await response.Content.ReadAsStringAsync();

 

}

 

/// <summary>

/// Display an error message to the user.

/// </summary>

/// <param name="result">The authentication result returned from AcquireTokenAsync().</param>

private static async void DisplayErrorWhenAcquireTokenFails(AuthenticationResult result)

{

MessageDialog dialog;

 

switch (result.Error)

{

case "authentication_canceled":

// User cancelled, so no need to display a message.

break;

case "temporarily_unavailable":

case "server_error":

dialog = new MessageDialog("Please retry the operation. If the error continues, please contact your administrator.",

"Sorry, an error has occurred.");

await dialog.ShowAsync();

break;

default:

// An error occurred when acquiring a token so show the error description in a MessageDialog.

dialog = new MessageDialog(string.Format(

"If the error continues, please contact your administrator.\n\nError: {0}\n\nError Description:\n\n{1}",

result.Error, result.ErrorDescription), "Sorry, an error has occurred.");

await dialog.ShowAsync();

break;

}

}

 

}

 Cheers !

Shraddha