Contents
Azure Application Registration
There is a big problem when you plan to work with Dynamics 365 from .NET Core SDK. SDK is not compatible with .NET Core. Alternative possibility to work with Dynamics 365 is OData service. Here is detail guide how to set up connection with sample code.
First you need to register new Application in Azure.
Then assign Dynamics 365 service access
Generate access token.
Don’t forget to copy and save key!
Dynamics User Permission
Now you need to create Azure Application delegated user in Dynamics 365. First copy Azure Application ID.
Now go to the Dynamics 365 application users and Create new one.
Change form selector to “Application User”.
Input “Application ID” and user information
Save it and don’t forget to assign roles in CRM
Test Console
Now is time to test OData connection. Code snipped from this resource. To authorize in Azure we need authority endpoint.
Ready to create .Net Core Sample Console
Here is code sample:
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace D365.REST
{
class Program
{
//Azure Application / Client ID
private const string ClientId = "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx";
//Azure Application Client Key / Secret
private const string ClientSecret = "xxxxxxxxxxx";
//Resource / CRM Url
private const string Resource = "https://xxxxx.crm4.dynamics.com";
//Guid is your Azure Active Directory Tenant Id
private const string Authority = "https://login.microsoftonline.com/ xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx /oauth2/token";
//private static AuthenticationResult _authResult;
private static string _accessToken;
static void Main(string[] args)
{
var getTokenTask = Task.Run(async () => await GetToken());
Task.WaitAll(getTokenTask);
if (getTokenTask.Result == null)
return;
//Deserialize the token response to get the access token
TokenResponse tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(getTokenTask.Result);
_accessToken = tokenResponse.access_token;
Task.WaitAll(Task.Run(async () => await DoWork()));
}
private static async Task DoWork()
{
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(Resource);
httpClient.Timeout = new TimeSpan(0, 2, 0);
httpClient.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
httpClient.DefaultRequestHeaders.Add("OData-Version", "4.0");
httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", _accessToken);
//Unbound Function
HttpResponseMessage whoAmIResponse =
await httpClient.GetAsync("api/data/v8.2/WhoAmI");
Guid userId;
if (whoAmIResponse.IsSuccessStatusCode)
{
JObject jWhoAmIResponse =
JObject.Parse(whoAmIResponse.Content.ReadAsStringAsync().Result);
userId = (Guid)jWhoAmIResponse["UserId"];
Console.WriteLine("WhoAmI " + userId);
}
else
return;
//Retrieve
HttpResponseMessage retrieveResponse =
await httpClient.GetAsync("api/data/v8.2/systemusers(" +
userId + ")?$select=fullname");
if (retrieveResponse.IsSuccessStatusCode)
{
JObject jRetrieveResponse =
JObject.Parse(retrieveResponse.Content.ReadAsStringAsync().Result);
string fullname = jRetrieveResponse["fullname"].ToString();
Console.WriteLine("Fullname " + fullname);
}
else
return;
Console.ReadLine();
}
}
private static async Task<string> GetToken()
{
using (HttpClient httpClient = new HttpClient())
{
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("resource", Resource),
new KeyValuePair<string, string>("client_id", ClientId),
new KeyValuePair<string, string>("client_secret", ClientSecret),
new KeyValuePair<string, string>("grant_type", "client_credentials")
});
HttpResponseMessage response = await httpClient.PostAsync(Authority, formContent);
return !response.IsSuccessStatusCode ? null
: response.Content.ReadAsStringAsync().Result;
}
}
}
}
namespace D365.REST
{
[DataContract]
public class TokenResponse
{
[DataMember]
public string token_type { get; set; }
[DataMember]
public string expires_in { get; set; }
[DataMember]
public string ext_expires_in { get; set; }
[DataMember]
public string expires_on { get; set; }
[DataMember]
public string not_before { get; set; }
[DataMember]
public string resource { get; set; }
[DataMember]
public string access_token { get; set; }
}
}
Profit!
--Andrey Paltusov--
comments powered by Disqus