Connecting to CRM 2013 Online SOAP and OData endpoint through External Client Application (Windows Forms Application)

With CRM 2013, external client application can now authenticate with the Microsoft Dynamics CRM OData and SOAP web service end points.

Steps:

  • Create a new windows application project in Visual Studio.
  • Right click the project in solution explorer and select Manage NuGet Packages.
  • Search Online and Install Active Directory Authentication Library.

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.
  • Specify Client App Url as ms-app://test

 

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

The sample code (uses the code found in SDK)

 

namespace Crm2013WindowsApp

{

public partial class MyApp : Form

{

public MyApp ()

{

InitializeComponent ();

}

private const string _clientID = "0a57c0ce-6624-42c7-9178-7cb0e44249c0" ;

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

 

private void Form1_Load (object sender , EventArgs e )

{

try

{

string redirectUri = "ms-app://test" ;

var authenticationContext = new AuthenticationContext ( "https://login.windows.net/common/wsfed" );

var authenticationResult = authenticationContext . AcquireToken ( "Microsoft.CRM" , "0a57c0ce-6624-42c7-9178-7cb0e44249c0" , new System . Uri ( redirectUri ));

var token = authenticationResult . AccessToken ;

 

//Call Soap

RetrieveMultipleSoap ( token , new string [] { "firstname" , "lastname" }, "contact" );  

// Call OData

Retrieve ( token , new string [] { "FirstName" , "LastName" }, "Contact" );  

}

catch( Exception ex )

{

MessageBox . Show ( "Error occured " + ex . Message );

}  

}   

public static async Task < string > RetrieveMultipleSoap ( 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://x.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 ();  

return responseBodyAsText ;

}

 

public static async Task < string > 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://x.crm5.dynamics.com/XRMServices/2011/OrganizationData.svc/" + entity + "Set?$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 ();  

return responseBodyAsText ;

}

}

}

 Cheers !

Shraddha