Sample Code to retrieve instances using Online Management API in Dynamics 365 Customer Engagement


With version 9.0 of Dynamics 365 CE we now have Online Admin API that supports the following operations like Create, Retrieve, Delete, Backup and Restore instances. The user needs to have the Global Administrator or Service Administrator role in the Office 365 tenant to perform these operations.

As a first step we need to register the application with Azure Active Directory.

https://nishantrana.me/2016/11/13/register-a-dynamics-365-app-with-azure-active-directory/

and get the values for

Client Id and Authority.

Get the Service URL here

https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/online-management-api/get-started-online-management-api#service-url

Sharing a sample code which can be used to retrieve all the instances in a specific tenant.

The sample code: –


public class MySampleApp
{

private const string Resource = "https://admin.services.crm.dynamics.com/";

// username and password
private const string UserName = "username.onmicrosoft.com";
private const string Password = "password";

// client id and authority of the application registered
private const string ClientId = "b2c5028d-57e6-4df7-9940-3243214948b";
private const string Authority = "https://login.microsoftonline.com/3432432e2-5fbe-4b78-a55a-bcb342d4f859/";

private static AuthenticationResult _authResult;

private static void Main(string[] args)
{
var authContext = new AuthenticationContext(Authority, false);
var credentials = new UserCredential(UserName, Password);

// Get the token
_authResult = authContext.AcquireToken(Resource, ClientId, credentials);

Task.WaitAll(Task.Run(async () => await GetInstances()));
}

private static async Task GetInstances()
{
var httpClient = new HttpClient
{
BaseAddress = new Uri(Resource),
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 retrieveResponse =
await httpClient.GetAsync("/api/v1/instances");

if (retrieveResponse.IsSuccessStatusCode)
{
var jRetrieveResponse =
retrieveResponse.Content.ReadAsStringAsync().Result;

var result = JArray.Parse(jRetrieveResponse);
foreach (var data in result)
Console.Write("Id " + data["Id"] + "\nUnique Name " + data["UniqueName"]);
}
}
}

Result: –

The other properties: –

SiteMapName in the AppModuleSiteMap is null or empty error while importing V9 Solution in Dynamics 365 Customer Engagement


We recently upgraded our Dev and Test environment to V 9.0.

Dev

Test

While importing a solution from Dev to Test which had SiteMap we got the below issue.

“The SiteMapName in the AppModuleSiteMap is null or empty”

It turns out that the following tags were required and were missing in the Customization.xml

We added that tag and were able to import the solution successfully.

Interestingly if we export the same solution from Test and search for this tag, it is again missing, however, we can see the following XML section added there

This section was not there in dev’s sitemap.

Hope it helps..

Different Updating Instance status during Dynamics 365 Upgrade


The day has come when we had scheduled the upgrade of our Dynamics 365 instance Test Instance(from 8.2 to 9.0).

We can see the below message during the scheduled time à “The update will being within 24 hours. No rescheduling is available”.

The following Reschedule Update option will go missing during the scheduled time.

After waiting for few minutes, we see the Update Status as Queue (Not Started)

Followed by the status as “Database Upgrade”

In between the Status message will be Backup and Restore.

https://docs.microsoft.com/en-in/dynamics365/customer-engagement/admin/manage-updates#update-status

Then it kept interchanging the status from Updating Instance (with no status) to Updating Instance – Database Upgrade for close to 2.5 hours.

Then although the status was Updating Instance the Open link got enabled after 2.5 hours.

Which opened the following notification

And finally, after 10 minutes or so à

We were all set with version 9.1

In total it took around 3 hours approximately.

Time to enjoy the successful upgrade and explore the new features ..

 

How to – Use Plugin on Pre-Validation Stage in Dynamics 365 CE


Recently we had a requirement to delete the Account record without deleting the associated Contact records.

If we try deleting the account record we’d get the following message box

The relationship definition can’t be updated as well to achieve this

So, we wrote a plugin on the pre-validation stage of pre-delete event of Account, which will retrieve and loop through all the child contact records and set its parent customer field as null.

In case of pre-operation the child records were not available.

</p>
<p>public void Execute(IServiceProvider serviceProvider)<br />
{<br />
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));<br />
IPluginExecutionContext pluginContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));<br />
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));<br />
IOrganizationService organizationService = serviceFactory.CreateOrganizationService(pluginContext.UserId);<br />
EntityReference targetEntity = (EntityReference)pluginContext.InputParameters["Target"];<br />
QueryExpression getContacts = new QueryExpression("contact");<br />
getContacts.Criteria.AddCondition(new ConditionExpression("parentcustomerid", ConditionOperator.Equal, targetEntity.Id));EntityCollection allContacts = organizationService.RetrieveMultiple(getContacts);foreach (Entity contact in allContacts.Entities)<br />
{<br />
Entity contactToBeUpdated = new Entity("contact");<br />
contactToBeUpdated.Id = contact.Id;<br />
contactToBeUpdated.Attributes["parentcustomerid"] = null;<br />
organizationService.Update(contactToBeUpdated);<br />
}}<br />

Another practical scenario

https://www.inogic.com/blog/2017/03/plugin-pre-validation-operation-to-show-an-error-message-as-well-as-log-the-error/

Hope it helps..

Advertisements

How to – Use RetrieveRecordChangeHistoryRequest to get Audit Detail in Dynamics 365 CE


Just sharing a sample code to retrieve the Audit Detail using RetrieveRecordChangeHistoryRequest.

RetrieveRecordChangeHistoryRequest changeRequest = new RetrieveRecordChangeHistoryRequest();
changeRequest.Target = new EntityReference("entitySchemaName", "entityId"));
RetrieveRecordChangeHistoryResponse changeResponse =
(RetrieveRecordChangeHistoryResponse)_service.Execute(changeRequest);

AuditDetailCollection auditDetailCollection = changeResponse.AuditDetailCollection;

foreach (AttributeAuditDetail attrAuditDetail in auditDetailCollection.AuditDetails)
{
var auditRecord = attrAuditDetail.AuditRecord;

Console.WriteLine("Entity: " + ((EntityReference)auditRecord.Attributes["objectid"]).LogicalName);
Console.WriteLine("Operation: " + auditRecord.FormattedValues["operation"]);
Console.WriteLine("Action: " + auditRecord.FormattedValues["action"]);

var newValueEntity = attrAuditDetail.NewValue;

foreach(var attrNewValue in newValueEntity.Attributes)
{
Console.WriteLine("New Key: " + attrNewValue.Key + "New Value: " + attrNewValue.Value);
}

var oldValueEntity = attrAuditDetail.OldValue;

foreach (var attrOldValue in oldValueEntity.Attributes)
{
Console.WriteLine("Old Key: " + attrOldValue.Key + "Old Value: " + attrOldValue.Value);
}
}


The record whose Audit History we are retrieving :

Output :

AuditDetail.AuditRecord :

AuditDetail.OldValue n NewValue:

Hope it helps..

Advertisements

Solved – Alternate Key not getting created on solution import in Dynamics 365


Recently, we moved our Solution from Development to Test. Then on running one of the SSIS Packages we got the below error

The specified key attributes are not a defined key for the entity [4] CRM service call returned an error:

On opening the Entity for customization, and checking for the key, we saw that it was in the Status Pending.

On opening the system job, there was no detail for the error.

We normally get this error, if there are records already available that have duplicate values for that alternate key field. However, in this case, there we no record as this entity was being moved first time in the Test.

Well to just fix this we thought of manually reactivating the key

However, that threw a new error that “Reactivate entity key is only supported for failed job.”

To fix this go to Settings à System Jobs à search for the failed system job and delete them

Now we will see the status as Failed

This time it will allow running the reactivation.

Finally,

Hope it helps..

Advertisements