Friday, 22 December 2023

How to Connect to Azure B2C using C#

 Below is the code related to how to connect to Azure AD B2C using B2CGraphClient. 


    1. Get Access Token using following approach : 

        

 this.clientId = clientId;

            this.clientSecret = clientSecret;

            this.tenant = tenant;


            // The AuthenticationContext is ADAL's primary class, in which you indicate the direcotry to use.

            this.authContext = new AuthenticationContext("https://login.microsoftonline.com/" + tenant);


            // The ClientCredential is where you pass in your client_id and client_secret, which are 

            // provided to Azure AD in order to receive an access_token using the app's identity.

            this.credential = new ClientCredential(clientId, clientSecret);


2.  Send Graph Request using below code : 


 // First, use ADAL to acquire a token using the app's identity (the credential)

            // The first parameter is the resource we want an access_token for; in this case, the Graph API.


            Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult result = await authContext.AcquireTokenAsync("https://graph.windows.net", credential);

            //AuthenticationResult result = authContext.AcquireToken("https://graph.windows.net", credential);


            // For B2C user managment, be sure to use the 1.6 Graph API version.

            HttpClient http = new HttpClient();

            string url = "https://graph.windows.net/" + tenant + api + "?" + Globals.aadGraphVersion;

            if (!string.IsNullOrEmpty(query))

            {

                url += "&" + query;

            }


            Console.ForegroundColor = ConsoleColor.Cyan;


            // Append the access token for the Graph API to the Authorization header of the request, using the Bearer scheme.

            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);

            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);

            HttpResponseMessage response = await http.SendAsync(request);


            if (!response.IsSuccessStatusCode)

            {

                string error = await response.Content.ReadAsStringAsync();

                object formatted = JsonConvert.DeserializeObject(error);

                throw new WebException("Error Calling the Graph API: \n" + JsonConvert.SerializeObject(formatted, Formatting.Indented));

            }


            Console.ForegroundColor = ConsoleColor.Green;


            await response.Content.ReadAsStringAsync();

How To Retrieve More than 5K Records in MS CRM

  Please find below sample code to check how to retrieve more than 5K Records in MS CRM using C# code :


Problem Statement : Query Expression can’t fetch more than 5k Records in Ms CRM

Create a Paging Programmatically and Execute data present in first page. Then proceed with other pages until execution completes for all Number of Records in Production.

C# Code to achieve Solution  using Query Expression :

  string countryLocale = "%" + countryId + "%";

                QueryExpression query = new QueryExpression("customerproductwarranty");

               

                // Or retrieve All Columns

                query.ColumnSet = new ColumnSet(true);

                ConditionExpression condition1 = new ConditionExpression();

                condition1.AttributeName = "locale";

                condition1.Operator = ConditionOperator.Like;

                condition1.Values.Add(countryLocale);

                FilterExpression filter1 = new FilterExpression();

                filter1.Conditions.Add(condition1);

                query.Criteria.AddFilter(filter1);

 

                query.PageInfo = new PagingInfo();

                query.PageInfo.Count = 1000;

                query.PageInfo.PageNumber = 1;

                query.PageInfo.ReturnTotalRecordCount = true;

                EntityCollection myContacts = service.RetrieveMultiple(query);

 

                Console.WriteLine("First set of Records retrieved are :" + myContacts.Entities.Count);

                objErrorLog.WriteErrorLog("First set of Records retrieved are :"+myContacts.Entities.Count);

                var queryResult = service.RetrieveMultiple(query);

                if (queryResult.Entities.Count > 0)

                {

                    count = customerWarrantyDateFormatFix(queryResult , i , service);

                    i += count;

                }

               while (myContacts.MoreRecords)

                {

                    query.PageInfo.PageNumber += 1;

                    query.PageInfo.PagingCookie = myContacts.PagingCookie;

                    myContacts = service.RetrieveMultiple(query);

                    Console.WriteLine("More Records retrieved are : " + myContacts.Entities.Count);

                    objErrorLog.WriteErrorLog("More Records retrieved are :" + myContacts.Entities.Count);

                    //Add to the collection

                    var queryResult1 = service.RetrieveMultiple(query);

                    if (queryResult1.Entities.Count > 0)

                    {               

                       count = customerWarrantyDateFormatFix(queryResult1 ,i, service);

                        i = count;

                    }

                                    }

             Place your functionalities inside method : customerWarrantyDateFormatFix so that Operations like Update / Get can be performed.

 

C# code to achieve using Fetch XML : 


string countryLocale = "%" + countryId + "%";

// int recordCreatedBeforeDays = createdBeforeDays;

// Define the fetch attributes.

// Set the number of records per page to retrieve.

int fetchCount = 5000;

// Initialize the page number.

int pageNumber = 1;

// Initialize the number of records.

int recordCount = 0;

// Specify the current paging cookie. For retrieving the first page, 

// pagingCookie should be null.

string pagingCookie = null;

            try

            {


String fetchRecordsfromCRMforNonAutoWarrantyCountries = @"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>

                      <entity name='contact'>

                       <all-attributes />

                        <order attribute='fullname' descending='false' />

                        <filter type='and'>

                          <condition attribute='locale' operator='like' value='" + countryLocale + @"' />

                          <condition attribute = 'emailaddress1' operator= 'not-null'  /> 

                          <condition attribute='modifiedon' value='" + lastXDays + @"' operator='last-x-days'/>

                        </filter>

                      </entity>

                    </fetch>";


                while (true)

                {

                    string xml = string.Empty;


                         xml = CreateXml(fetchRecordsfromCRMforNonAutoWarrantyCountries, pagingCookie, pageNumber, fetchCount);

 

                    // Excute the fetch query and get the xml result.

                    RetrieveMultipleRequest fetchRequest1 = new RetrieveMultipleRequest

                    {

                        Query = new FetchExpression(xml)

                    };


EntityCollection returnCollection = ((RetrieveMultipleResponse)service.Execute(fetchRequest1)).EntityCollection;

                    

}

                    // Check for morerecords, if it returns 1.

                    if (returnCollection.MoreRecords)

                    {

                        Console.WriteLine("\n****************\nPage number {0}\n****************", pageNumber);

                        objErrorLog.WriteErrorLog("\n****************\nPage number {0}\n****************", pageNumber.ToString());


                        // Increment the page number to retrieve the next page.

                        pageNumber++;

                        //refresh the connection

                        service = (IOrganizationService) conn.OrganizationWebProxyClient ?? (IOrganizationService) conn.OrganizationServiceProxy;

objErrorLog.WriteErrorLog("connection refreshed");

                        Console.WriteLine("Connection refreshed");

                        // Set the paging cookie to the paging cookie returned from current results.                            

                        pagingCookie = returnCollection.PagingCookie;

                    }

                    else

                    {

                        // If no more records in the result nodes, exit the loop.

                        break;

                    }

    }

            catch (Exception e)

            {

                Console.WriteLine(" No Records fetched for given Query  ");

                objErrorLog.WriteErrorLog(" No Records fetched with Exception  " + e);

            }



Azure Key Vault Connection to connect to MS CRM

 Below is the sample code regarding how to connect to Azure Key Vault to get Credentials to connect to any Ms CRM Organizations 


 // Azure Key Vault Connections 

            string keyVaultName = ConfigurationManager.AppSettings["KeyVaultName"];

            string crmUrl = ConfigurationManager.AppSettings["crmUrl"];


            string password = "";

            var kvUri = String.Format(ConfigurationManager.AppSettings["KeyVaultUrl"], keyVaultName);


            var credential = new Azure.Identity.ClientSecretCredential(ConfigurationManager.AppSettings["KeyVaultAzureTenantID"], ConfigurationManager.AppSettings["KeyVaultAzureClientID"], ConfigurationManager.AppSettings["KeyVaultAzureClientSecret"]);

            var client = new SecretClient(new Uri(kvUri), credential);


            var user = client.GetSecret(ConfigurationManager.AppSettings["KeyValueUserIDSecret"]).Value;

            userName = user.Value;


            var pwd = client.GetSecret(ConfigurationManager.AppSettings["KeyValuePasswordSecret"]).Value;

            password = pwd.Value;


            string connectionString = string.Format("AuthType=OAuth;Username={0};Password={1};Url={2};AppId=760c6b53-9d70-4fe0-8b08-2b6001f7069d;RedirectUri=app://468550f1-718b-416c-bd12-a686589aadbb;LoginPrompt=Never;RequireNewInstance = True", userName, password, crmUrl);


            var conn = new CrmServiceClient(connectionString);


IOrganizationService service;

            service = (IOrganizationService)conn.OrganizationWebProxyClient ?? (IOrganizationService)conn.OrganizationServiceProxy;