Microsoft Dynamics CRM Plug-in Template for Visual Studio

The Microsoft Dynamics CRM User Experience team is always looking to improve our customers’ experience when using the SDK. Past examples of our work in this area include publishing the Plug-in Developer tool and the Plug-in Registration tool for registering plug-ins and custom workflow activities. This blog is about another useful tool for your development toolbox, a C# and VB plug-in template for Microsoft Visual Studio 2008.

Since I have to write plug-ins now and then, I wanted to come up with a standard Visual Studio code template for writing a plug-in. In the code template provided in this blog I have included the following features:

  • A plug-in constructor that supports passing secure and non-secure information to the plug-in
  • A standard Execute method that retrieves and verifies information from the passed context parameter
  • Web service proxy instantiation
  • Basic handling of SOAP exceptions
  • Custom methods that instantiate the Web service proxies for those plug-ins that execute in a child pipeline

To install the template into Visual Studio, copy the downloaded zip file into your Visual Studio 2008\Templates\ProjectTemplates\Visual C# (or Visual Basic) folder.

To use the template, simply create a new project in Visual Studio, select a C# or Visual Basic project type in the New Project dialog box, and then select the MSCRM Plug-in template.

clip_image002

After creating the new project, you may need to remove and then add the project references to the Microsoft.Crm.Sdk and Microsoft.Crm.SdkTypeProxy assemblies in Solution Explorer if Visual Studio cannot find the assemblies on your system when you build the project. In the project’s property page on the Signing tab, remember to check Sign the assembly and create a new key file.

Below is the C# version of the plug-in code if you just want the code and don’t need the Visual Studio template.

   1: using System;
   2: using System.Collections.Generic;
   3: using Microsoft.Win32;
   4:
   5: // Microsoft Dynamics CRM namespaces
   6: using Microsoft.Crm.Sdk;
   7: using Microsoft.Crm.SdkTypeProxy;
   8: using Microsoft.Crm.SdkTypeProxy.Metadata;
   9:
  10: namespace Crm.Plugins
  11: {
  12:     public class MyPlugin : IPlugin
  13:     {
  14:         // Provide configuration information that can be passed to a plug-in at run-time.
  15:         private string _secureInformation;
  16:         private string _unsecureInformation;
  17:
  18:         // Note: Due to caching, Microsoft Dynamics CRM does not invoke the plug-in 
  19:         // contructor every time the plug-in is executed.
  20:
  21:         // Related SDK topic: Writing the Plug-in Constructor
  22:         public MyPlugin(string unsecureInfo, string secureInfo)
  23:         {
  24:             _secureInformation   = secureInfo;
  25:             _unsecureInformation = unsecureInfo;
  26:         }
  27:
  28:         // Related SDK topic: Writing a Plug-in
  29:         public void Execute(IPluginExecutionContext context)
  30:         {
  31:             DynamicEntity entity = null;
  32:
  33:             // Check if the InputParameters property bag contains a target
  34:             // of the current operation and that target is of type DynamicEntity.
  35:             if (context.InputParameters.Properties.Contains(ParameterName.Target) &&
  36:                context.InputParameters.Properties[ParameterName.Target] is DynamicEntity)
  37:             {
  38:                 // Obtain the target business entity from the input parmameters.
  39:                 entity = (DynamicEntity)context.InputParameters.Properties[ParameterName.Target];
  40:
  41:                 // TODO Test for an entity type and message supported by your plug-in.
  42:                 // if (entity.Name != EntityName.account.ToString()) { return; }
  43:                 // if (context.MessageName != MessageName.Create.ToString()) { return; }
  44:             }
  45:             else
  46:             {
  47:                 return;
  48:             }
  49:
  50:             try
  51:             {
  52:                 // Create a Microsoft Dynamics CRM Web service proxy.
  53:                 // TODO Uncomment or comment out the appropriate statement.
  54:
  55:                 // For a plug-in running in the child pipeline, use this statement.
  56:                 // CrmService crmService = CreateCrmService(context, true);
  57:
  58:                 // For a plug-in running in the parent pipeline, use this statement.
  59:                 ICrmService crmService = context.CreateCrmService(true);
  60:
  61:                 // TODO Plug-in business logic goes here.
  62:
  63:             }
  64:             catch (System.Web.Services.Protocols.SoapException ex)
  65:             {
  66:                 throw new InvalidPluginExecutionException(
  67:                     String.Format("An error occurred in the {0} plug-in.",
  68:                        this.GetType().ToString()),
  69:                     ex);
  70:             }
  71:         }
  72:
  73:         #region Private methods
  74:         /// <summary>
  75:         /// Creates a CrmService proxy for plug-ins that execute in the child pipeline.
  76:         /// </summary>
  77:         /// <param name="context">The execution context that was passed to the plug-ins Execute method.</param>
  78:         /// <param name="flag">Set to True to use impersonation.</param>
  79:         /// <returns>A CrmServce instance.</returns>
  80:         private CrmService CreateCrmService(IPluginExecutionContext context, Boolean flag)
  81:         {
  82:             CrmAuthenticationToken authToken = new CrmAuthenticationToken();
  83:             authToken.AuthenticationType = 0;
  84:             authToken.OrganizationName = context.OrganizationName;
  85:
  86:             // Include support for impersonation.
  87:             if (flag)
  88:                 authToken.CallerId = context.UserId;
  89:             else
  90:                 authToken.CallerId = context.InitiatingUserId;
  91:
  92:             CrmService service = new CrmService();
  93:             service.CrmAuthenticationTokenValue = authToken;
  94:             service.UseDefaultCredentials = true;
  95:
  96:              // Include support for infinite loop detection.
  97:             CorrelationToken corToken = new CorrelationToken();
  98:             corToken.CorrelationId = context.CorrelationId;
  99:             corToken.CorrelationUpdatedTime = context.CorrelationUpdatedTime;
 100:             corToken.Depth = context.Depth;
 101:
 102:             RegistryKey regkey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\MSCRM");
 103:
 104:             service.Url = String.Concat(regkey.GetValue("ServerUrl").ToString(), "/2007/crmservice.asmx");
 105:             service.CorrelationTokenValue = corToken;
 106:
 107:             return service;
 108:         }
 109:
 110:         /// <summary>
 111:         /// Creates a MetadataService proxy for plug-ins that execute in the child pipeline.
 112:         /// </summary>
 113:         /// <param name="context">The execution context that was passed to the plug-ins Execute method.</param>
 114:         /// <param name="flag">Set to True to use impersonation.</param>
 115:         /// <returns>A MetadataServce instance.</returns>
 116:         private MetadataService CreateMetadataService(IPluginExecutionContext context, Boolean flag)
 117:         {
 118:             CrmAuthenticationToken authToken = new CrmAuthenticationToken();
 119:             authToken.AuthenticationType = 0;
 120:             authToken.OrganizationName = context.OrganizationName;
 121:
 122:             // Include support for impersonation.
 123:             if (flag)
 124:                 authToken.CallerId = context.UserId;
 125:             else
 126:                 authToken.CallerId = context.InitiatingUserId;
 127:
 128:             MetadataService service = new MetadataService();
 129:             service.CrmAuthenticationTokenValue = authToken;
 130:             service.UseDefaultCredentials = true;
 131:
 132:             RegistryKey regkey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\MSCRM");
 133:
 134:             service.Url = String.Concat(regkey.GetValue("ServerUrl").ToString(), "/2007/metadataservice.asmx");
 135:
 136:             return service;
 137:         }
 138:         #endregion Private Methods
 139:     }
 140: }