This article is an in-depth discussion about the three aforementioned interfaces that are very common in Dynamics CRM, especially when developing plugins and are present in the CRM SDK.
Let’s start by ITracingService, which is by far the simplest of the three.
Imagine the following scenario:
Someone you know developed a plugin for CRM. Unfortunately, that person has then left the company and the plugin has been installed on several clients and it is your job to figure out what’s wrong with it on a particular situation.
The normal course of action here is to take the Platform traces and see if these contain any errors or messages from that plugin, but upon looking deeper into the traces, you discover that no messages about the plugin activity are being recorded in the traces.
Then you go and get yourself a copy of the code, and see that in the plugin code, there is no reference whatsoever to ITracingService, so there is no way for you to know exactly what is your plugin doing once you run it.
As you could see from the scenario above, you had no chance of knowing what actions the plugin trying to achieve. Here is where ITracingService best comes into play.
ITracingService allows you to use the existing CRM Tracing Service in order to perform run-time logging of any action that your plugin is taking in the CRM System, as long as you code them to be registered. This runtime logging is then very useful when you have problems with your plugin and need to resort to looking into the Platform Traces to understand what is going on.
Let’s look at the members of this interface:
void Trace(
string format,
params object[] args
)
You can use this method in one of three ways (please bear in mind that these are merely examples, you put in more information, and I am omitting the object for simplicity):
Trace(“This will be written to the plugin tracing log”)
string format = “Formatting”;
string coolest =”coolest”;
string traces = “traces”;
Trace(“{0} is the {1} way to write {2}”, formatting, coolest, traces)
object[] array = new object[] { “Formatting”, “coolest”, “traces”};
Trace(“{0} is the {1} way to write {2}”, array);
How can we invoke the Tracing Service?
The tracing service can be invoked in the following fashion. Within a plugin, you have a mandatory method called Execute, which in turn holds a parameter that implements IServiceProvider. It is from this parameter that we will be invoking the tracing service
//some code omitted for brevity>
using System;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
public class MyPlugin: IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
…
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
…
}
}
If you register the plugin as sandboxed and enable plug-in tracing on the System Settings, you can then use the Plugin Trace Logs under settings to see what is your plugin doing.
And that is it for the ITracingService. Onwards to the IOrganizationServiceFactory:
IOrganizationServiceFactory is the interface that allows us to be able to invoke CRM’s Organization Service so that we can then use it in order to read/write data and/or metadata into CRM.
A little interesting note: The “Factory” suffix in the name is a tell-tale sign that we are using a design pattern (see Design Patterns by the authors known as the Gang of Four (Gamma, Helm, Johnson and Vlissides), Addison-Wesley, ISBN13: 978-0-201-63361-0, ISBN10: 978-0-201-63361-2.
There are two factory patterns: Abstract Factory and the Factory Method. Since we’re dealing with an interface here, this would fall on the Abstract Factory pattern.
How we instantiate the Organization service from the factory? First we need to grab a hold of the service provider in the plugins Execute method and invoke it like so:
(IOrganizationServiceFactory) factory = (IOrganizationServiceFactory)service.GetServiceProvider(typeof(IOrganizationServiceFactory));
Now that we have our factory set up, let’s invoke the service
(IOrganizationService) service = (IOrganizationService)factory.CreateOrganizationService(null);
Note that we’ve placed null in the parameter.
If it is set to null, then the user that will be used to make all calls is the SYSTEM user. This user is a special user in the CRM system, alongside with another special user called INTEGRATION.
When it is set to the Guid.Empty constant (00000000-0000-0000-0000-000000000000,
doc link), it will be called with the user id existent in the plugin’s context (IPluginExecutionContext.UserId) or with the user id in the workflow context (IWorflowContext.UserId).
Any other value will indicate that we’re using a specific user within the system (Side note: If you are having issues with a plugin/workflow and you have an On Premises system, collect the CRM Platform traces (How to
here), and investigate for possible missing privileges).
That’s it for IOrganizationServiceFactory. Now, for the final instalment in this post: IPluginExecutionContext.
When a plug-in is running, it needs to have information regarding to what is its current status and information that has been provided to it, or information that it will provide to other plugins. That information is known as its context.
What does this “context” hold exactly?
Amongst other properties (see full list in the
doc link), we have the following properties, which we find the most important to be aware of:
Property
|
Meaning
|
Depth
|
Indicates the current depth of execution in the call stack. This property is of paramount importance when you face situations where you have to call code that can make the plug-in make recursive calls to itself and therefore prevent a situation of infinite looping.
Current limits ( doc link) are 8 levels deep and one hour for the plug-in execution to timeout. Please be sensible when changing these limits in your system.
|
InitiatingUserId
|
This is the system Guid for the user that started the execution of the plug-in.
|
Stage
|
This indicates the stage in which the plug-in is executing.
Valid values currently are:
10 – Pre-Validation
20 – Pre-Operation
40 – Post-Operation
Other valid values, but are either deprecated or represent the system stage:
30 – Operation (this you can’t take control of or register a plug-in on, this is where the actual operation takes place)
50 – Post-Operation (currently deprecated.
|
We encourage you to look into the documentation itself with regards to the IPluginExecutionContext interface, as it derives many of its properties from IExecutionContext interface
Hope this post has shed some light on your questions.
Best Regards
EMEA Dynamics CRM Support Team