D365 V9{Upgrade}: Sharing record using Web API and custom action

In D365 V8, GrantAccessRequest message was not available for which we were using SOAP request in JavaScript to share a record with a user.

As part of upgrade activities, since SOAP requests are going to be deprecated, now we have replaced our SOAP request with Web API and calling custom action from Web API as we have GrantAccessRequest message in D365 V9. More details here.

Below are the steps we performed :

  • Create a Global custom action which takes 3 input parameters and Activate it.
    • EntityName: Schema name of entity
    • RecordId: GUID of record to be shared
    • UserId: GUID of user with which records will be shared


  • Create a plugin for the custom action “sab_MAFFinanceSharePhoneCallorOfferDetailwithUser”
  • For the corresponding plugin xml element in crmregister file, use PrimaryEntityName=”none” and MessageName=”sab_maffinancesharephonecallorofferdetailwithuser”


  • Use below line of code in the constructor of the plugin

this.RegisteredEvents.Add(new Tuple(40, "sab_MAFFinanceSharePhoneCallorOfferDetailwithUser", "", new Action(this.ExecuteCrmPlugin)));


  • Use the below block of code in the plugin created which reads the input parameters sent and shares the record(gives Read Access to the User Id passed to the Record Id passed)

protected override void ExecuteCrmPlugin(LocalPluginContext localContext)
if (localContext == null)
throw new InvalidPluginExecutionException("localContext");
string entityName = string.Empty;
Guid recordId = Guid.Empty;
Guid userId = Guid.Empty;

if (localContext.PluginExecutionContext.InputParameters.Contains("EntityName"))
entityName = (string)localContext.PluginExecutionContext.InputParameters["EntityName"];
if (localContext.PluginExecutionContext.InputParameters.Contains("RecordId"))
recordId = new Guid((string)localContext.PluginExecutionContext.InputParameters["RecordId"]);
if (localContext.PluginExecutionContext.InputParameters.Contains("UserId"))
userId = new Guid((string)localContext.PluginExecutionContext.InputParameters["UserId"]);

if (!string.IsNullOrEmpty(entityName) && recordId != Guid.Empty && userId != Guid.Empty)
var userIdReference = new EntityReference("systemuser", userId);
var grantAccessRequest = new GrantAccessRequest
PrincipalAccess = new PrincipalAccess
AccessMask = AccessRights.ReadAccess,
Principal = userIdReference
Target = new EntityReference(entityName, recordId)

  • In JavaScript, use the below code to call the custom action in Web API

TestSharePhoneCallRecord: function () {
try {
var parameters = {};
parameters.EntityName = "phonecall";// for testing purpose
parameters.RecordId = "196ABB32-88D7-E811-A955-000D3AB5A6AE"; //GUID of an existing record
parameters.UserId = "B0BBCE82-4541-E811-811E-5065F38B5691"; //GUID of a user

var req = new XMLHttpRequest();
req.open("POST", Xrm.Utility.getGlobalContext().getClientUrl() + "/api/data/v9.0/sab_MAFFinanceSharePhoneCallorOfferDetailwithUser", true);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function () {
if (this.readyState === 4) {
req.onreadystatechange = null;
if (this.status === 204) {
//Success - No Return Data - Do Something
} else {
catch (ex) {
//Xrm.Utility.alertDialog('Exception: ' + ex);

  • To test, call the above JavaScript code on Load of Phone Call form. Then Save the changes and Publish it.


  • Next time, when we load the Phone call record, we can see that the phone call record has been shared with user.



Hope it helps !!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.