Sub Title

Thursday, May 31, 2018

Plugin Input and output parameters in Dynamics 365

The InputParameters property contains the data that is in the request message currently being processed by the event execution pipeline. Your plug-in code can access this data. The property is of type ParameterCollection where the keys to access the request data are the names of the actual public properties in the request. As an example, take a look at CreateRequest. One property of CreateRequest is named Target, which is of type Entity. This is the entity currently being operated upon by the platform. To access the data of the entity you would use the name “Target” as the key in the input parameter collection. You also need to cast the returned instance.



// The InputParameters collection contains all the data passed in the message request.
if (context.InputParameters.Contains("Target") &&
    context.InputParameters["Target"] is Entity)
{
    // Obtain the target entity from the input parameters.
    Entity entity = (Entity)context.InputParameters["Target"];

Note that not all requests contain a Target property that is of type Entity, so you have to look at each request or response. For example, DeleteRequest has a Target property, but its type is EntityReference. The preceding code example would be changed as follows.



// The InputParameters collection contains all the data passed in the message request.
if (context.InputParameters.Contains("Target") &&    context.InputParameters["Target"] is EntityReference)
{
    // Obtain the target entity from the input parameters.
    EntityReference entity = (EntityReference)context.InputParameters["Target"];
}
Once you have access to the entity data, you can read and modify it. Any data changes to the context performed by plug-ins registered in stage 10 or 20 of the pipeline are passed in the context to the core operation in stage 30.

Important

Not all fields in an entity record that are passed to a plug-in through the context can be modified. You should check the field’s IsValidForUpdate metadata property to verify that it isn’t set to false. Attempting to change the value of a field that can’t be updated results in an exception.


Similarly, the OutputParameters property contains the data that is in the response message, for example CreateResponse, currently being passed through the event execution pipeline. However, only synchronous post-event and asynchronous registered plug-ins have OutputParameters populated as the response is the result of the core platform operation. The property is of type ParameterCollection where the keys to access the response data are the names of the actual public properties in the response.

Below is the table to explain more about input parameters.

Message Request
InputParameter
Description
Create
Target
Target Contain the Entity with the attributes of current triggering record.
Update
Target
Target Contain the Entity with the attributes whose values have been modified, leadid (primarykey of lead) as well those attributes that have forceSubmit true.
Delete
Target
Target Contain the EntityReference of deleted entity record.
Associate/Disassociate
Relationship,
Target,
RelatedEntities


Relationship Contain the Relationship name for which this plugin fired.
Target Contain the 
EntityReference of record.
RelatedEntities
 Contain the EntityReferenceCollection of Related Entities record.
Win/Lose Request Opportunity
OpportunityClose
OpportunityClose Contain the Entity which is the activity that is created while performing the Win/Lose operation and it contain the attribute opportunityid which give us the opportunity on which this action is perform.

Monday, May 28, 2018

Mobile client metadata is corrupted due to null reference issue in Dynamics 365

Recently, I had experienced a significant failure with the Dynamics 365 for Tablets client. It had seemed to present itself out of the blue, without any real reasoning or trigger behind it.  As we reviewed the errors presented via developer tools in Chrome while loading the tablet client in a browser, we saw a significant error related to the metadata sync.
Tablet Error - Metadata sync
Developer tools output from Chrome Browser when accessing Tablet app via browser
We also found when we attempted to Prepare Client Customizations for the solution, we received the following error message:
prepare client customizations error
D365 cryptic error message when attempting to prepare client customizations for the mobile client
As it turns out, the mobile client metadata was corrupted due to a null reference issue in a Word template. Document templates are tied to metadata of entities and attributes, which is unfortunately not checked for nor handled via exception by D365 when metadata generation takes place. Once we removed the corrupted template, this resolved the issue.
So When you delete an attribute or entity, verify the commensurate changes are made to any Word or Excel Templates, else Mobile client will fail in a quite spectacular way!

Thursday, May 24, 2018

Compare two security rules

David Yack’s fantastic Xrm.Tools has a security role explorer that allows you to easily compare two Dynamics 365 security roles, identify what is unique to each role, and what the differences are.
In your browser, go to Xrm.Tools. Click “Sign in” and log in to your Office 365 account. Note–you can save this step by logging in to Dynamics 365 first, then opening another tab and going to xrm.tools. You still need to click “sign in,” but it will authenticate you to your Office 365 account.
In the lower left quadrant, click “Explore Roles Now!”
On the next screen, select the organization environment where you wish to compare roles.
Click “Compare Roles.”
Select the roles you wish to compare and click “compare.”
The tool will then provide you with a comparison of the two roles:
  • Permissions unique to role 1
  • Permissions unique to role 2
  • Differences between the two roles
  • Similarities between the two roles

CrmServiceClient and multiple instances

If you are using Microsoft.Xrm.Tooling.Connector.CrmServiceClient and relying on nuget to reference the assembly in your project (as you should) then you need to be aware of what seems to be an odd behavior but is, in fact, a bug fix.
Run the following code:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var s1 = $@"Url=https://org1.crm.dynamics.com;
   AuthType=Office365;
   UserName=user@org1.onmicrosoft.com;
   Password=passwordorg1";
var s2 = $@"Url=https://org2.crm.dynamics.com;
   AuthType=Office365;
   UserName=user@org2.onmicrosoft.com;
   Password=passwordorg2";
using (var crmSvc = new CrmServiceClient(s1))
{
  Console.WriteLine($"Ready={crmSvc.IsReady}");
  Console.WriteLine($"User={crmSvc.GetMyCrmUserId()}");
  Console.WriteLine(
    $"Org={crmSvc.ConnectedOrgFriendlyName}");
}
using (var crmSvc = new CrmServiceClient(s2))
{
  Console.WriteLine($"Ready={crmSvc.IsReady}");
  Console.WriteLine($"User={crmSvc.GetMyCrmUserId()}");
  Console.WriteLine(
    $"Org={crmSvc.ConnectedOrgFriendlyName}");
}
And get:
1
2
3
4
5
6
Ready=True
User=8fa1eeae-dead-beef-dead-b6b5240774e4
Org=org1
Ready=True
User=8fa1eeae-dead-beef-dead-b6b5240774e4
Org=org1
Same user and org? Despite the use of the disposable object, connection didn’t change at all?!
Yes, this is correct and, if you were relying on similar code before, you were riding on top of the unintended buggy behavior. Correct and documented behavior is for the connection to be cached and reused unless you specify RequireNewInstance flag either as part of the connection string:
1
2
3
4
5
var s2 = $@"RequireNewInstance=True;
  Url=https://barbaz.crm.dynamics.com;
  AuthType=Office365;
  UserName=user@barbaz.onmicrosoft.com;
  Password=password";
or as part of a constructor (useUniqueInstance parameter):
1
2
3
4
5
6
CrmServiceClient crmSvc = new CrmServiceClient(
    "user@barbaz.onmicrosoft.com",
    CrmServiceClient.MakeSecureString("password"),
    "NorthAmerica", "barbaz",
    useUniqueInstance: true,
    useSsl: true, isOffice365: true);
The change is reflected in the notes on nuget package:
RequireNewInstance=True will now properly create a unique connection instance, RequireNewInstance=false, will now properly reuse the cached instance of the connection, default is ‘false’
If you are connecting to more than one instance in your code or, if you’d like to maintain two separate connections with the separate instances of metadata, cache, etc, make sure that you use this flag.