Write a custom Azure-aware plug-in

 

Applies To: Dynamics 365 (online), Dynamics 365 (on-premises), Dynamics CRM 2016, Dynamics CRM Online

Writing a plug-in that works with Microsoft Azure is similar to writing any other Microsoft Dynamics 365 plug-in. However, in addition to invoking any desired web service methods, the plug-in must include code to initiate posting the execution context to the Microsoft Azure Service Bus.

In This Topic

Plug-in design considerations

Write the plug-in code

Plug-in registration

Handle a failed service bus post

Plug-in design considerations

For a plug-in that executes synchronously, the recommended design is for the plug-in to send a message to Microsoft Azure for the purpose of retrieving information from a listener application or other external service. Use of a two-way or REST contract on the Microsoft Azure Service Bus endpoint allows a data string to be returned to the plug-in.

It is not recommended that a synchronous plug-in use the Microsoft Azure Service Bus to update data with an external service. Problems can arise if the external service becomes unavailable or if there is a lot of data to update. Synchronous plug-ins should execute fast and not hold up all logged in users of an organization while a lengthy operation is performed. In addition, if a rollback of the current core operation that invoked the plug-in occurs, any data changes made by the plug-in are undone. This could leave Microsoft Dynamics 365 and an external service in an unsynchronized state.

Note that it is possible for synchronous registered plug-ins to post the execution context to the Microsoft Azure Service Bus.

Write the plug-in code

In the following sample plug-in code has been added to obtain the Microsoft Azure service provider and initiate posting the execution context to the service bus by calling Execute. Tracing code has been added to facilitate debugging of the plug-in because the plug-in must run in the sandbox.


using System;
using System.Diagnostics;
using System.Threading;
using System.Runtime.Serialization;

using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;

using Microsoft.Xrm.Sdk;

namespace Microsoft.Crm.Sdk.Samples
{
    /// <summary>
    /// A custom plug-in that can post the execution context of the current message to the Windows
    /// Azure Service Bus. The plug-in also demonstrates tracing which assist with
    /// debugging for plug-ins that are registered in the sandbox.
    /// </summary>
    /// <remarks>This sample requires that a service endpoint be created first, and its ID passed
    /// to the plug-in constructor through the unsecure configuration parameter when the plug-in
    /// step is registered.</remarks>
    public sealed class SandboxPlugin : IPlugin
    {
        private Guid serviceEndpointId; 

        /// <summary>
        /// Constructor.
        /// </summary>
        public SandboxPlugin(string config)
        {
            if (String.IsNullOrEmpty(config) || !Guid.TryParse(config, out serviceEndpointId))
            {
                throw new InvalidPluginExecutionException("Service endpoint ID should be passed as config.");
            }
        }

        public void Execute(IServiceProvider serviceProvider)
        {
            // Retrieve the execution context.
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            // Extract the tracing service.
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            if (tracingService == null)
                throw new InvalidPluginExecutionException("Failed to retrieve the tracing service.");

            IServiceEndpointNotificationService cloudService = (IServiceEndpointNotificationService)serviceProvider.GetService(typeof(IServiceEndpointNotificationService));
            if (cloudService == null)
                throw new InvalidPluginExecutionException("Failed to retrieve the service bus service.");

            try
            {
                tracingService.Trace("Posting the execution context.");
                string response = cloudService.Execute(new EntityReference("serviceendpoint", serviceEndpointId), context);
                if (!String.IsNullOrEmpty(response))
                {
                    tracingService.Trace("Response = {0}", response);
                }
                tracingService.Trace("Done.");
            }
            catch (Exception e)
            {
                tracingService.Trace("Exception: {0}", e.ToString());
                throw;
            }
        }
    }
}

In your plug-in code, you can update the writeable data in the context before initiating the post. For example, you can add a key/value pair to the shared variables in the context.

Plug-in registration

There are a few restrictions when you register a Microsoft Azure aware custom plug-in. The plug-in must be registered to execute in the sandbox. Because of this, the plug-in is limited to calling Microsoft Dynamics 365 SDK methods, Microsoft Azure solution methods, or accessing a network using a web client. No other external access, such as access to a local file system, is allowed.

For a plug-in registered to execute in asynchronous mode, this also means that the order of plug-in execution compared to other asynchronous plug-ins is not guaranteed. In addition, asynchronous plug-ins always execute after the Microsoft Dynamics 365 core operation.

Handle a failed service bus post

The expected behavior from a failed service bus post is dependent on whether the plug-in was registered for synchronous or asynchronous execution. For asynchronous plug-ins, the system job that actually posts the execution context to the service bus will retry the post. For a synchronous registered plug-in, an exception is returned. More information: Manage of run-time errors

Important

For asynchronous registered plug-ins only, when the asynchronous job that posts to the Microsoft Azure Service Bus is retried after a post failure, the entire plug-in logic is executed again. Because of this, don’t add any other logic to the custom Microsoft Azure aware plug-in other than just modifying the context and posting to the service bus.

For a plug-in registered to execute asynchronously, the RemoteExecutionContext contained in the body of the message that is sent over the service bus includes a OperationId property and a OperationCreatedOn property. These properties contain the same data as the AsyncOperationId and CreatedOn attributes of the related System Job (AsyncOperation) record. These additional properties facilitate sequencing and duplicate detection if the Microsoft Azure Service Bus post must be retried.

See Also

Azure extensions for Microsoft Dynamics 365
Work with Dynamics 365 data in your Azure solution
Write a plug-in
Plug-in isolation, trusts, and statistics
Event execution pipeline
Register and Deploy Plug-Ins

Microsoft Dynamics 365

© 2016 Microsoft. All rights reserved. Copyright