Archive
[Step by Step] Postman tool to test Dynamics 365 online Web API
In this article, lets see how to connect and test Dynamics 365 Web API requests using Postman tool, step by step along with troubleshooting steps.
Note: Refer article for steps to connect to Dataverse Web API from Postman tool.
Those who are not familiar with Postman tool, it is a request composer tool, which allows you to authenticate to your Dynamics 365 instance, compose Web API requests, send them, and view response. Link to download
Prerequisites:
- Download Postman tool
- Dynamics 365 online instance. (Subscribe to 30 days trial, if you have not one)
- Azure Active Directory Portal (You need to login with your Office 365 Credentials)
Register App in Azure Active Directory:
As a first step, you need to register an App in Azure Active Directory (i.e., oAuth) by following below steps
- Connect to the Azure Active Directory (AD) Portal with your Office 365 credentials.
- Register a new Dynamics 365 App by following steps mentioned here
- Once you are done with App registration, copy ‘Application ID’ and ‘Home page’ values, which you need to use next steps.
Setup your Postman tool:
Create ‘Environment’
- Create a new Postman ‘Environment’ with below variables. This is one time activity for a single D365 instance.
- url : Your Dynamics 365 URL
- clientid : ‘Application ID’ from Azure AD, generated in above section.
- version : Dynamics version
- webapiurl : Set this to {{url}}/api/data/v{{version}}/
- callback : ‘Home page’ value from Azure AD, generated in above section.
- authurl : Set this to https://login.microsoftonline.com/common/oauth2/authorize?resource={{url}}
- I created a new ‘Environment’ with name ‘DynamicsCRM’ and it looks as below
Generate oAuth Access Token:
Post ‘Environment’ creation, we need to generate oAuth Access Token. This is one time activity for a single D365 instance.
- Make sure you select ‘Environment’ created in previous section. In my case its ‘DynamicsCRM’.
- Under ‘Authorization’ tab, set ‘Type’ to ‘oAuth 2.0’ and click on ‘Get New Access Token’.
- In the ‘GET NEW ACCESS TOKEN SCREEN’ make sure you set values as below.
- Click ‘Request Token’ and system will prompt you for credentials, pass your O365 credentials.
- When you click ‘Next’, you may encounter “response_type ‘token’ is not enabled for the application” exception.
- To fix this, make sure in your Azure AD Application’s manifest “oauth2AllowImplicitFlow” property is set to ‘true’
- You may also encounter “The reply url specified in the request does not match the reply urls configured for the application“.
- To fix this, make sure you set the Postman’s ‘Environment’ -> ‘callback’ variable set correctly.
- Click ‘Continue’ to complete the ‘Access Token’ generation process.
- On successful ‘Access Token’ generation, you would get the screen as below.
- Click ‘Use Token’.
That’s it! we are done with settings and its time to test the Dynamics API’s with Postman
Test by executing ‘WhoAmI’ request:
- Make sure you select the right ‘Environment’ and generated your ‘Access Token’.
- Select ‘GET’ operation and set the URL as {{webapiurl}}WhoAmI
- Click ‘Send’
- You should get “200 OK” response up on success.
- You may get “401 Unauthorized” response.
- To fix this, make sure you set “Add authorization data to” to “Request Headers”.
🙂
[Code Snippet] Authenticate and Perform Operations using D365 Web API and C#
As a continuation to my last article Different ways to connect authenticate dynamics 365 , lets see how to Authenticate Dynamics Web API using C#.
Note: Be mindful that this approach is different than connecting to Dynamics 365 using Microsoft.XRM.Tooling.Connector dll approach. This article explains how to connect to D365 using Web API which is no SDK .dll approach.
Pre-requisites:
- Dynamics 365 subscription. Go for 30 days trail if not already have one.
- Register an App in “Azure Active Directory” and get ‘Application ID’ and other parameters.
- Visual Studio Console application
Steps to Register App in “Azure Active Directory”:
We need to register an application with Microsoft Azure Active Directory so that it can connect to the Microsoft Dynamics 365 server, authenticate using OAuth, and access the web services.
- Connect to Microsoft Office Admin Center.
- From the ‘Admin Centers’ menu, select ‘Azure Active Directory’.
- From the “Azure Active Directory admin center’, select ‘App registrations’ -> New application registration
- Provide below details
- Name – Provide name of the App. Can be any name minimum of 4 characters.
- Application Type – Choose ‘Native’ as we are going to call Web API from Console application
- Sign-on URL – Can be a valid URL. This you need to pass in the Console application.
- Click ‘Create’ to complete the App creation
- Post creation, open the App and copy the ‘Application ID’ which you need in Console application.
- Click on ‘Settings’ -> Required Permissions -> Add ‘Dynamics CRM Online’ -> Enable the permission as below
- Finally, select the App, click on ‘Endpoints’ and copy ‘OAuth 2.0 Authorization Endpoint‘ which you would need in Console Application.
Steps to connect to D365 WebAPI from Console Application:
After registering App in ‘Azure Active Directory’ now its time to connect to D365 Web API from Console Application.
- Create a new C# Console Application project
- Add below 2 Nuget packages to the project
- Newtonsoft.Json
- Microsoft.IdentityModel.Clients.ActiveDirectory
Code Snippet:
In the ‘Program.cs’ file add below
- Add Using Namespaces:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Net;
- Add Global Variables:
// O365 User Name and Password
private const string userName = “rajeevpentyala@exploreSept18.onmicrosoft.com”;
private const string password = “YourPasswordHere”;
// D365 Application Url
private const string serviceUrl = “https://exploresept18.crm.dynamics.com”;
// Azure APP Application Id
private const string applicationId = “1549b5b3-XXXX-XXXX-94be-7a8eeaf3e081”;
// Redirct Uri specified during registration of application
private const string RedirectUri = “https://localhost”;
// OAuth 2.0 Authorization Endpoint copied from Azure APP
private const string authorityUri = “https://login.microsoftonline.com/9e3039aa-XXXX-XXXX-80e1-f67d40bd01cf/oauth2/authorize”;private static AuthenticationResult authResult = null;
- Main Method:
private static void Main(string[] args){
// Code to connect to D365
var credentials = new UserPasswordCredential(userName, password);
var context = new AuthenticationContext(authorityUri);
authResult = context.AcquireTokenAsync(serviceUrl, applicationId, credentials).Result;// Call CRUD operations
// Task.WaitAll(Task.Run(async () => await ExecuteWhoAmI()));
// Task.WaitAll(Task.Run(async () => await CreateRecord()));
// Task.WaitAll(Task.Run(async () => await RetrieveContacts()));}
- Code to call WhoAmIRequest:
private static async Task ExecuteWhoAmI(){
var httpClient = new HttpClient{
BaseAddress = new Uri(serviceUrl),
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”, authResult.AccessToken);// Add this line for TLS complaience
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;// Call WhoAmI
var retrieveResponse = await httpClient.GetAsync(“api/data/v9.0/WhoAmI”);
if (retrieveResponse.IsSuccessStatusCode){
var jRetrieveResponse = JObject.Parse(retrieveResponse.Content.ReadAsStringAsync().Result);var currUserId = (Guid)jRetrieveResponse[“UserId”];
var businessId = (Guid)jRetrieveResponse[“BusinessUnitId”];Console.WriteLine(“My User Id – ” + currUserId);
Console.WriteLine(“My User Id – ” + businessId);
Console.ReadLine();
}
}
- Code to Retrieve Records:
private static async Task RetrieveContacts(){
var httpClient = new HttpClient{
BaseAddress = new Uri(serviceUrl),
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”, authResult.AccessToken);// Add this line for TLS complaience
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;// Retrieve Contacts
var retrieveResponse = await httpClient.GetAsync(“api/data/v9.0/contacts”);
if (retrieveResponse.IsSuccessStatusCode){
var jRetrieveResponse = JObject.Parse(retrieveResponse.Content.ReadAsStringAsync().Result);dynamic collContacts = JsonConvert.DeserializeObject(jRetrieveResponse.ToString());
foreach (var data in collContacts.value){
Console.WriteLine(“Contact Name – ” + data.fullname.Value);
}Console.ReadLine();
}
}
- Code to Create Record:
private static async Task CreateRecord(){
JObject contact1 = new JObject{
{ “firstname”, “Peter” },
{ “lastname”, “Cambel” },
{ “annualincome”, 80000 }
};contact1[“jobtitle”] = “Junior Developer”;
var httpClient = new HttpClient{
BaseAddress = new Uri(serviceUrl + “/api/data/v9.0/”),
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”, authResult.AccessToken);// Add this line for TLS complaience
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, “contacts”){
Content = new StringContent(contact1.ToString(), Encoding.UTF8, “application/json”)
};HttpResponseMessage response = await httpClient.SendAsync(request);if (response.StatusCode == HttpStatusCode.NoContent) //204 {
Console.WriteLine(“POST succeeded, entity created!”);
//optionally process response message headers or body here, for example:
var entityUri = response.Headers.GetValues(“OData-EntityId”).FirstOrDefault();// Update the Contact record
Task.WaitAll(Task.Run(async () => await UpdateRecord(entityUri)));// Delete the contact record
Task.WaitAll(Task.Run(async () => await DeleteRecord(entityUri)));
}
else{
Console.WriteLine(“Operation failed: {0}”, response.ReasonPhrase);
throw new CrmHttpResponseException(response.Content);
}
}
- Code to Update Record:
private static async Task UpdateRecord(string contactUri){
JObject contact1Add = new JObject{
{ “annualincome”, 80000 },
{ “jobtitle”, “Junior Developer” }
};var httpClient = new HttpClient{
BaseAddress = new Uri(serviceUrl + “/api/data/v9.0/”),
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”, authResult.AccessToken);HttpRequestMessage updateRequest1 = new HttpRequestMessage(new HttpMethod(“PATCH“), contactUri){
Content = new StringContent(contact1Add.ToString(), Encoding.UTF8, “application/json”)
};
HttpResponseMessage updateResponse1 = await httpClient.SendAsync(updateRequest1);if (updateResponse1.StatusCode == HttpStatusCode.NoContent) //204 {
//Console.WriteLine(“Contact ‘{0} {1}’ updated with job title” +
// ” and annual income.”, contactUri.GetValue(“firstname”),
// contactUri.GetValue(“lastname”));
}
else{
Console.WriteLine(“Failed to update contact for reason: {0}”, updateResponse1.ReasonPhrase);
throw new CrmHttpResponseException(updateResponse1.Content);
}}
- Code to Delete Record:
private static async Task DeleteRecord(string contactUri){
var httpClient = new HttpClient{
BaseAddress = new Uri(serviceUrl + “/api/data/v9.0/”),
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”, authResult.AccessToken);var response = httpClient.DeleteAsync(contactUri).Result;
if (response.IsSuccessStatusCode) //200-299 {
Console.WriteLine(“Contact has been deleted!!!”);
}
else if (response.StatusCode == HttpStatusCode.NotFound) //404 {
//Entity may have been deleted by another user or via cascade delete.
}
else //Failed to delete {
Console.WriteLine(“Error while deletion; Message: ” + response.Content);
}
}
🙂