Base classes for Dynamics 365 plugins and workflows. Wraps boilerplate code and offers a series of extension methods to streamline plugin and custom activities development.
Get it from Nuget:
PM> Install-Package XrmUtils.CrmSdk.PluginExtensions
Documentation will be provide soon. Bellow is a summary commonly used functionality.
When creating a plugin, inherit from PluginBase
instead of implementing the IPlugin
interface from the SDK.
In this example, the plugin class is decorated with a series of attributes that not only self-documents the plugin registration but are used at runtime to validate the registration. If registration is different than expected, an InvalidPluginExecutionException
will be thrown before the Execute
method is reached.
The LocalPluginContext
passed as an argument to the Execute
method has all the services you would normally use in a plugin (such as ITracingService
and IOrganizationService
).
using XrmUtils.Extensions;
using XrmUtils.Extensions.Plugins;
[Message("update")]
[PrimaryEntity("account")]
[ExecutionMode(ExecutionMode.Asynchronous)]
[Stage(PipelineStage.PostOperation)]
public class TrackCreditLimit : PluginBase
{
protected override void Execute(LocalPluginContext localContext)
{
// your implementation here
}
}
A fully implemented plugin, note the Execute
method only has the necessary business logic:
[Message("update")]
[PrimaryEntity("account")]
[ExecutionMode(ExecutionMode.Asynchronous)]
[Stage(PipelineStage.PostOperation)]
public class TrackCreditLimit : PluginBase
{
protected override void Execute(LocalPluginContext localContext)
{
var target = localContext.GetTargetEntity();
var image = localContext.GetPreImage("MyImage", throwIfNull: true);
if(target.AttributeHasChanged("creditlimit", image))
{
Entity oldLimit;
localContext.Trace("Credit limit has changed. Creating audit log.");
oldLimit = new Entity("creditlimittracking");
oldLimit.AddOrUpdateAttribute("limit", image.GetAttributeValue<Money>("creditlimit"));
localContext.Trace("Creating new record.");
localContext.OrganizationService.Create(oldLimit);
}
else
{
localContext.Trace("Credit limit didn't change.");
}
}
}
In the above examples, all calls to localContext.Trace
are routed to the default instance of Dynamics 365 ITracingService
.
There may be an instance where you want to wrap the tracing service so you can le's say, dump additional information on a custom entity.
You can inject yout own service by overriding the base class method CreateTracingService
.
This method received the original tracing service which you can use to initialize your custom implementation if required.
public class TrackCreditLimit : PluginBase
{
protected override ITracingService CreateTracingService(ITracingService crmTracingService)
{
return MyCustomFactory.CreateService(crmTracingService);
}
protected override void Execute(LocalPluginContext localContext)
{
// this call you use your own tracing service.
localContext.Trace("Using my own trace.");
}
}
When creating a custom workflow activity, inherit from WorkflowActivityBase
instead of CodeActivity
.
The LocalWorkflowContext
passed as an argument to the Execute
method has all the services you would normally use in a custom activity (such as ITracingService
and IOrganizationService
).
using XrmUtils.Extensions.Plugins;
class MyCustomActivity : WorkflowActivityBase
{
[Input("Full name")]
public InArgument<string> FullName { get; set; }
[Output("Result")]
public OutArgument<string> Result { get; set; }
protected override void Execute(LocalWorkflowContext localContext)
{
var name = FullName.Get(localContext.ExecutionContext);
var greetings = $"Hello {name}!";
Result.Set(localContext.ExecutionContext, greetings);
}
}
While this project os dostributed under MIT license, it may have dependencies on 3rd party software distributed under different licenses.