Aug 29, 2019

Connect to WebApi using ClientId and Secret

We can now register our Dynamics 365 CE in Azure Active Directory, so that platform can be accessed through different client applications using OAuth. Idea behind is client applications can securely access WebApi using just Client Id and Secret.

Below is a code snippet with C# in .NET Framework 4.6.2 to achieve it.

Click here to see how to register D365 CE in Azure

Only two NuGet packages required. (Please note one of them are not in latest version)


using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Clients.ActiveDirectory;


namespace ConnectWebApiWithClientId
{
    class Program
    {
        static void Main(string[] args)
        {
            Task.WaitAll(Task.Run(async () => await Auth()));
        }

        public static async Task Auth()
        {
            string url = "https://SumeTest.crm.dynamics.com";
            string clientId = "5d83f9es-a577-4s01-ab9b-9513e39k970c";
            string secret = "MvrHJ2T2YK7NabYFRSOfrEqLMME/1OMW8n6sVBA7zxI=";
            string apiVersion = "9.1";

            try
            {
                var userCredential = new ClientCredential(clientId, secret);
                string webApiUrl = $"{url}/api/data/v{apiVersion}/";

                var authParameters = AuthenticationParameters.CreateFromResourceUrlAsync(new Uri(webApiUrl)).Result;

                var authContext = new AuthenticationContext(authParameters.Authority, false);
                var authResult = await authContext.AcquireTokenAsync(url, userCredential);
                var authHeader = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);

                using (var client = new HttpClient())
                {
                    client.BaseAddress = new Uri(webApiUrl);
                    client.DefaultRequestHeaders.Authorization = authHeader;

                    // Use the WhoAmI function
                    var response = client.GetAsync("WhoAmI").Result;
                    if (response.IsSuccessStatusCode)
                    {
                        Console.WriteLine("Authenticated Successfully");
                        Console.WriteLine("Environement : {0}", url);
                        Console.WriteLine();
                    }
                    else
                    {
                        Console.WriteLine("The request failed with a status of '{0}'", response.ReasonPhrase);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex.InnerException;
            }
            Console.WriteLine("Click Enter to Exit Application");
            Console.ReadLine();
        }
    }
}

Hope this helps.

Aug 20, 2019

Programmatical formatting of System Job Error string

When analyzing the errors in Dynamics 365 CE, we usually need to check System Jobs. In some cases, it may be required to create file (in most cases a Excel/ csv) with errors for further analysis. In such cases, it would be a troublesome exercise when it comes to handle the error message programmatically because they contain all kinds of error-prone characteristics such as spaces, many characters those become painful especially if you going to create importable file.

For example, consider below typical error message;

[Mxd.Crm.Workflows.Integration: Mxd.Crm.Workflows.Integration.CreateSalesData]
[Mxd.Crm.Workflows.Integration (1.0.0.0): Mxd.Crm.Workflows.Integration.CreateSalesData]

Correlation Id: a72ec1c9-ba30-422f-9b11-fcc7fd269e33, Initiating User: 0c089e94-0b42-e911-a878-000d3a6a0a90
Initialise Sales Manager 
Call to SalesManager to create Integration Request 
Retrieving Salesman (CONTACT) for "" [689825e6-1b90-e966-a882-000d3a6a065c]
Retrieving all Sales Codes for Salesman
Total number of Sales Enteries: 1
Retrieving ERP Data for Cales Code "East" [8180hh6c-2ac8-e711-a825-000d3ae0a7f8]
Data Area = "888"
WARNING: Region does not specify Regional Manager
Retrieving Salesman Profile "Jay Thompson" [d411a654-1c90-e911-a882-000d3a6a065c]
Invalid Plugin Execution exception detected: An item with the same sames code has already been added.



Error Message:

Unhandled exception: 
Exception type: Microsoft.Xrm.Sdk.InvalidPluginExecutionException
Message: An item with the same sames code has already been added.

Anyway, below is the simple method I wrote to format this, so that clean string is passed. This is so simple but time someone need to spend on this could be really costly. So thought of sharing.

public static string CleanErrorMsg(string valString)
{
var strWithSpaces = valString.Replace("\" ", " ").Replace(Environment.NewLine, " ").Replace(",", " ").Replace("\r\n", " ").Trim();
return Regex.Replace(strWithSpaces, @"\s+", " ");
}

This really removes below;
- troublesome characters
- Line breakers
- Extra spaces (more than one space together)