Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Writing a Plug-in
Collapse the table of content
Expand the table of content

Writing a Plug-in

banner art

[Applies to: Microsoft Dynamics CRM 4.0]

Find the latest SDK documentation: CRM 2015 SDK

Plug-ins must implement the Microsoft.Crm.Sdk.IPlugin interface as shown here.

Example

[C#]
using System;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;

namespace MyPlugins
{
   public class AccountCreateHandler: IPlugin
   {
      public void Execute(IPluginExecutionContext context)
      {
         // Do something here.
      }
   }
}

For this minimal code to compile, you must add references to the Microsoft.Crm.Sdk and Microsoft.Crm.SdkTypeProxy assemblies that are provided in the SDK\Bin folder of the Microsoft Dynamics CRM SDK samples. You also have to add a reference for System.Web.Services. For more information, see About the Assemblies.

The execution context that is passed as an argument to the Execute method contains information from the Request message being passed through the event execution pipeline. The context can include such information as the primary entity for which the event was fired, snapshots (images) of the entity before or after the core operation, the input parameters to the Request message, and so on. For a detailed description of the context, see Event Handler Context.

Note For improved performance, Microsoft Dynamics CRM caches plug-in instances. The plug-in's Execute method should be written to be stateless because the constructor is not called for every invocation of the plug-in. In addition, multiple threads could be running the plug-in at the same time. All per invocation state information is stored in the context. This means that you should not use global class variables in plug-ins.

Plug-in assemblies can contain one or more plug-in types as shown in the following code sample.

Example

[C#]
using System;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;

namespace MyPlugins
{
   public class AccountCreateHandler: IPlugin
   {
      public void Execute(IPluginExecutionContext context)
      {
         // Do something here.
      }
   }
   public class AccountUpdateHandler: IPlugin
   {
      public void Execute(IPluginExecutionContext context)
      {
         // Do something here.
      }
   }
}

The sample code shown here demonstrates the minimal code needed for a plug-in. A typical plug-in should verify the information passed in the context, access that information, perform the required business operation, and handle exceptions.

Tip An alternate approach is to rely on correct plug-in registration resulting in a plug-n that executes under specific run-time conditions. When the plug-in executes, assume that the data passed to the plug-in in the context are properly populated. This would remove the need to perform so many checks and make the code more readable.

The following sample demonstrates a simple plug-in class that creates a task activity to follow up with the customer in one week. The plug-in must be registered to execute after (post-event) an account is created in Microsoft Dynamics CRM.

Example

[C#]
using System;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;

namespace Microsoft.Crm.Sdk.Walkthrough
{
   public class AccountCreateHandler: IPlugin
   {
      public void Execute(IPluginExecutionContext context)
      {
         DynamicEntity entity = null;

         // Check whether the input parameters property bag contains a target
         // of the create operation and that target is of type DynamicEntity.
         if (context.InputParameters.Properties.Contains("Target") &&
            context.InputParameters.Properties["Target"] is DynamicEntity)
         {
            // Obtain the target business entity from the input parmameters.
            entity = (DynamicEntity)context.InputParameters.Properties["Target"];

            // Verify that the entity represents an account.
            if (entity.Name != EntityName.account.ToString()) { return; }
         }
         else
         {
            return;
         }

         try
         {
            // Create a task activity to follow up with the account customer in 7 days. 
            DynamicEntity followup = new DynamicEntity();
            followup.Name = EntityName.task.ToString();

            followup.Properties = new PropertyCollection();
            followup.Properties.Add(new StringProperty("subject", "Send e-mail to the new customer."));
            followup.Properties.Add(new StringProperty("description", 
               "Follow up with the customer. Check if there are any new issues that need resolution."));

            followup.Properties.Add(new CrmDateTimeProperty("scheduledstart", 
               CrmTypes.CreateCrmDateTimeFromUniversal(DateTime.Now.AddDays(7))));
            followup.Properties.Add(new CrmDateTimeProperty("scheduledend", 
               CrmTypes.CreateCrmDateTimeFromUniversal(DateTime.Now.AddDays(7))));

            followup.Properties.Add(new StringProperty("category",
               context.PrimaryEntityName));
 
            // Refer to the new account in the task activity.
            if (context.OutputParameters.Properties.Contains("id"))
            {
               Lookup lookup = new Lookup();
               lookup.Value = new Guid(context.OutputParameters.Properties["id"].ToString());
               lookup.type = EntityName.account.ToString();

               followup.Properties.Add(
                  new LookupProperty("regardingobjectid", lookup));
            }

            TargetCreateDynamic targetCreate = new TargetCreateDynamic();
            targetCreate.Entity = followup;

            // Create the request object.
            CreateRequest create = new CreateRequest();
            create.Target = targetCreate;

            // Execute the request.
            ICrmService service = context.CreateCrmService(true);
            CreateResponse created = (CreateResponse)service.Execute(create);
         }
         catch (System.Web.Services.Protocols.SoapException ex)
         {
            throw new InvalidPluginExecutionException(
                  "An error occurred in the AccountCreateHandler plug-in.", ex);
         }
      }
   }
}

This example begins by obtaining the target entity from the execution context method parameter. The code then verifies that the entity is an account because this plug-in is designed to be registered for an account creation event. After it performs some business related logic, in this case creating a task activity instance, the code creates the task activity on the Microsoft Dynamics CRM server. Notice that the CreateCrmService method in the execution context is used to create an instance of the CrmService proxy. A catch statement is used to trap any thrown SOAP exceptions from the Web service. The catch block creates a new exception that contains a custom message that has the SOAP exception as the inner exception (System.Exception.InnerException). The Microsoft Dynamics CRM platform handles any exceptions thrown in plug-ins by displaying the exception message (System.Exception.Message) in a dialog of the user interface.

After you compile the plug-in, you must sign the assembly and deploy it to the Microsoft Dynamics CRM server. For more information about deploying a plug-in assembly, see Registering a Plug-in.

See Also

Concepts


© 2010 Microsoft Corporation. All rights reserved.


Show:
© 2015 Microsoft