Tag Archives: dynamics crm web api external application

{Knowhow} How to execute Web API calls to Microsoft Dynamics CRM from an external ASP.NET web application

Microsoft Web API has delighted all and specially if you have a penchant towards exploring the API features, then Web API must have thrilled you by this time. Many consultants and experts, including myself, have written blogs on how to leverage the Web API features in Dynamics CRM.

But all these far, all the examples have been written in javascript. To elaborate most of the examples are on

  • Using web API from within Microsoft Dynamics CRM webresources
  • Using web API from an external HTML page using javascript and adal.js

Web API uses OAuth 2.0 protocol for authorization. However when you are making Web API calls from within Dynamics CRM, the entire nuances of OAuth 2.0 authorization is hidden from you. All you need to do is send a well formatted request and get the response back, parse the json response and get the data back in the application to use.

For the second example, although it will expose you greatly to the nuances of OAuth 2.0 protocol  but there is a subtle difference when you execute Web API calls from browser based application (like javascript/ jquery) and from a server based application like ASP.NET web application. The main difference is that in the first case, you would not need the client secret to get the access token. The authentication is implicit and you get the access token in just one call to the authorization endpoint. For the second case you would need to first get the authorization code by asking the end-user to enter his credentials and then once you get the authorization code, you would need to make a second call to the token endpoint to get the access token using authorization code + client_id + client_Secret.

If you are not aware of the OAuth 2.0 mechanisms, I would strongly suggest to first check for the OAuth documentations or you may go through my below blog post.

https://debajmecrm.com/2016/02/23/understanding-in-depth-cross-origin-resource-sharing-cors-in-dynamics-crm-2016/

The above post first gives you an introduction to the OAuth 2.0 protocol and then how to use that to connect to Dynamics CRM Web API endpoint from an external HTML Page. The post also covers on how to register the application in azure AD and get the client id and the client secret. Before you read further I would strongly suggest you go through the above post and understand how OAuth 2.0 works from CRM perspective.

After I wrote the above blog post, I received lot of requests personally if I can provide and code of how to make the same call from ASP.NET web application. Well your wish is granted. Here I will show you end-end on how to fetch data from Dynamics CRM Web API from a ASP.NET web application.

 

  • Create a ASP.NET web application project with a single web page. I named it default.aspx.
  • Go to the design mode and the markup should look like below.

image

The markup should contain

  1. A Login button which when the user clicks will take him/ her to the authentication screen.
  2. The label will display the name of the user once the user is authenticated.
  3. Get Accounts Button will retrieve the list of accounts when clicked.
  4. GridView will show the list of accounts retrieved once the Get Accounts button is clicked.

The above link explains how to add Dynamics CRM AD in Azure and register the application in Dynamics AD and how to get the client id and the client secret. Please make a note of the client id and specially the client secret which is visible immediately after saving. Please note that the client secret is visible only for the first time. If you come back later, you won’t be able to view it.

  • For this demo, I will keep these values in the web.config file. However do not keep the client id and client secret in the web.config specially the client secret. It’s very sensitive information. You should have some better ways of managing the same.

<appSettings>
<add key=”client_id” value=”f8a39dc3-338b-4018-b67e-6dbaa846f469″/>
<add key=”client_secret” value=”<your client secret>”/>
<add key=”tenant” value=”xrmtr14.onmicrosoft.com”/>
<add key=”redirect_url” value=”
http://localhost:52432/default.aspx”/>
<add key=”resource” value=”
https://xrmtr14.crm.dynamics.com”/>
</appSettings>

  • Now add a reference to the Active Directory authentication library and NewtonSoft.json.dll. The best way to do this is using Nuget Packages. For Active Directory Authentication Library type ‘Microsoft IdentityModel’ in the search box.

image

image

  • Now come to code-behind file (default.aspx.cs) and copy the entire code from below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using System.Configuration;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Net;
using System.Web.Script.Serialization;
using Newtonsoft.Json;

namespace DynamicsCRMWebApiConnector
{
public partial class _default : System.Web.UI.Page
{
const string AuthorityUri = “
https://login.windows.net/{0}/oauth2/authorize”;
        const string CompleteAuthUri = “https://login.windows.net/{0}/oauth2/authorize?response_type=code&client_id={1}&resource={2}&redirect_uri={3}”;
        Configurations _configuration;

        protected void Page_Init(object sender, EventArgs e)
{
this.PopulateConfigurations();
}

        protected void Page_Load(object sender, EventArgs e)
{
var queryString = Request.QueryString;

            // means authorization code has been received
if(queryString != null && queryString[“code”] != null)
{
var authCode = queryString[“code”];

                // get the access token using the authorization code
TokenCache tokenCache = new TokenCache();
AuthenticationContext authContext = new AuthenticationContext(string.Format(AuthorityUri, _configuration.ADTenant), tokenCache);
ClientCredential clientCredentials = new ClientCredential(_configuration.ClientId, _configuration.ClientSecret);

                AuthenticationResult authResult = authContext.AcquireTokenByAuthorizationCode(authCode, new Uri(_configuration.RedirectUri), clientCredentials);

                if(authResult.UserInfo != null)
{
this.UserInfoLabel.Text = string.Format(“Welcome: {0} {1}”, authResult.UserInfo.GivenName, authResult.UserInfo.FamilyName);
Session[“AuthResult”] = authResult;
}
}
}

        protected void Login_Click(object sender, EventArgs e)
{
var authorityUri = this.GetAuthorizationUrl();

            Response.Redirect(authorityUri);
}

        protected void GetAccountsButton_Click(object sender, EventArgs e)
{
if (Session[“AuthResult”] != null)
{
var authResult = (AuthenticationResult)Session[“AuthResult”];
var webRequest = (HttpWebRequest)WebRequest.Create(new Uri(“
https://xrmtr14.crm.dynamics.com/api/data/v8.0/accounts?$select=name,address1_city&$top=10″));
webRequest.Method = “GET”;
webRequest.ContentLength = 0;
webRequest.Headers.Add(“Authorization”, String.Format(“Bearer {0}”, authResult.AccessToken));
webRequest.Headers.Add(“OData-MaxVersion”, “4.0”);
webRequest.Headers.Add(“OData-Version”, “4.0”);
webRequest.ContentType = “application/json; charset=utf-8”;

                using (var response = webRequest.GetResponse() as System.Net.HttpWebResponse)
{
//Get reader from response stream
using (var reader = new System.IO.StreamReader(response.GetResponseStream()))
{
var accounts = new List<Account>();
string responseContent = reader.ReadToEnd();

                        dynamic dynamicObj = JsonConvert.DeserializeObject(responseContent);

                        foreach(var data in dynamicObj.value)
{
var account = new Account
{
AccountName = data.name.Value,
City = data.address1_city != null ? data.address1_city.Value : string.Empty
};

                            accounts.Add(account);
}

                        AccountsGridView.DataSource = accounts;
AccountsGridView.DataBind();
}
}
}
}

        #region Methods

        private void PopulateConfigurations()
{
_configuration = new Configurations
{
ADTenant = ConfigurationManager.AppSettings[“tenant”],
ClientId = ConfigurationManager.AppSettings[“client_id”],
ClientSecret = ConfigurationManager.AppSettings[“client_secret”],
RedirectUri = ConfigurationManager.AppSettings[“redirect_url”],
Resource = ConfigurationManager.AppSettings[“resource”]
};
}

        private string GetAuthorizationUrl()
{
return string.Format(CompleteAuthUri, _configuration.ADTenant, _configuration.ClientId, _configuration.Resource, Server.UrlEncode(_configuration.RedirectUri));
}

        #endregion
}
}

public class Account
{
public string AccountName { get; set; }

        public string City { get; set; }
}

 

public class Configurations
{
public string ClientId { get; set; }

        public string ClientSecret { get; set; }

        public string ADTenant { get; set; }

        public string Resource { get; set; }

        public string RedirectUri { get; set; }

    }

  • I have created two classes ‘Account’ and ‘Configurations’ in the above the code. Check for the class definitions just above this line.
  • So let me explain the code a bit here. In the Page_Init method, I retrieve all the values from the web.config file and populate the Configurations class’s object with those values.
  • Next look for the code in the Login Button Click handler Login_Click. First we get the URI where the user would be redirected to authorize himself. In that URI we pass the redirect url as well so that when the authentication completes, the control comes back to this page only.
  • Once the user authenticates, the control will come back to this page and the Page_Load event would fire. The AuthorizationCode would be present in the querystring of the url with the key=code.
  • the Page_Load checks for the authorization code in the query string and then it send another request for the access token. This time it sends the authorization code + client id + client secret. The code makes use of the Microsoft Active Directory Authentication library to get the access token.
  • Finally when the ‘Get Accounts’ button is clicked, a HttpWebRequest is made with the token specified in the header of the request and we get the list of accounts. If everything works fine, your final thing would look something like below.

image

Hope this helps!