Export (0) Print
Expand All

Creating a CRM Post-Callout Object Using Visual Studio .NET

CRM 1.0

The following steps outline how to create a post-callout object for Microsoft CRM using Visual Studio .NET and either Microsoft Visual Basic® .NET or Microsoft Visual C#® .NET.

  1. Launch Visual Studio .NET.
  2. Click File, click New, and then select Project.
  3. Select either Visual Basic projects or Visual C# projects depending on your preference.
  4. Select the Class Library template.
  5. Assign a name to your project such as CRMCallout and pick a location to save your work.
  6. Click the OK button to create the project.
  7. Add a reference to the System.EnterpriseServices namespace. To do this, right-click your project in the Solution Explorer, then select the Add Reference option from the context menu. Select the System.EnterpriseServices component from the list box and click the Select button.  Click the OK button to continue.
  8. Rename the Class1.vb or Class1.cs file in the Solution Explorer to a name more descriptive such as Callout.vb or Callout.cs.
  9. At the top of the code file, add the following statements to specify the namespaces needed:
[C#]
      using System.EnterpriseServices;
      using System.Runtime.InteropServices;

[Visual Basic .NET]
      Imports System.EnterpriseServices
      Imports System.Runtime.InteropServices

  1. Add the following statements before the namespace declaration to set the assembly options:
[C#]
[assembly: ApplicationName("Callout Example")]
[assembly: ApplicationActivation(ActivationOption.Server)]
[assembly: ApplicationAccessControl(false,
           AccessChecksLevel=AccessChecksLevelOption.ApplicationComponent)]

[Visual Basic .NET]
<Assembly: ApplicationName("Callout Example")>
<Assembly: ApplicationActivation(ActivationOption.Server)> 
<Assembly: ApplicationAccessControl(False,
           AccessChecksLevel:=AccessChecksLevelOption.ApplicationComponent)>

These attributes help specify how the .NET assembly will operate with COM+ services. The ApplicationName attribute allows one to specify the name of the COM+ services application that will host the .NET assembly when it is imported into COM+. You can specify any name you would like here. The ApplicationActivation attribute specifies the type of COM+ application being created. This attribute uses an enumeration called ActivationOption which specifies that the application is a server application. This means that when the component is activated, it will be hosted in a process separate from the process that called it. The ApplicationAccessControl attribute specifies whether the component will perform any access level checks.

Note   The ApplicationAccessControl attribute is required for Microsoft CRM 1.2 and the .NET Framework version 1.1. Under the .NET Framework 1.1, the COM+ security configuration is enabled by default if this attribute is not present in the assembly. This is a change in the behavior from the .NET Framework version 1.0 where it was disabled by default.

  1. You must implement an interface called ICRMCallout for the object. For specifics on the interface, refer back to the beginning of this article. Add the following code to your code file inside the namespace block to create the interface:
[C#]
[GuidAttribute("F4233E5B-17DC-4661-9ABC-6707A9F99215")]

public interface ICRMCallout 
{
void PostCreate(int ObjectType, string ObjectId, string OrigObjectXml);
void PostUpdate(int ObjectType, string ObjectId, string OrigObjectXml);
void PostDelete(int ObjectType, string ObjectId);
}

[Visual Basic .NET]
<GuidAttribute("F4233E5B-17DC-4661-9ABC-6707A9F99215")> _
Public Interface ICRMCallout
Sub PostCreate(ByVal ObjectType As Integer,
      ByVal ObjectID As String, ByVal OrigObjectXML As String)
Sub PostUpdate(ByVal ObjectType As Integer,
      ByVal ObjectID As String, ByVal OrigObjectXML As String)
Sub PostDelete(ByVal ObjectType As Integer,
      ByVal ObjectID As String)      
End Interface

  1. Create a public class in the code file that inherits from ServicedComponent and implements the ICRMCallout interface. An example follows:
[C#]
public class CRMCaller : ServicedComponent, ICRMCallout

[Visual Basic .NET]
Public Class CRMCaller
    Inherits ServicedComponent
    Implements CRMCallout.ICRMCallout

  1. At the top of the code file, add the following statements to specify the namespaces needed:
[C#]
      using System.EnterpriseServices;
      using System.Runtime.InteropServices;

[Visual Basic .NET]
      Imports System.EnterpriseServices
      Imports System.Runtime.InteropServices

  1. A globally unique identifier (GUID) for the class must be defined and assigned to the class. You can create your own GUID using the GuidGen utility that is distributed with Visual Studio .NET. This utility creates a GUID that can be copied to the clipboard and then pasted into this code file. You can run it from the Create GUID option of the Tools menu.
  2. Assign this GUID to the class by inserting it into an attribute like the following just before your class declaration:
[C#]
[GuidAttribute("AA4AD2AC-97B8-4d24-8E81-388A655DDBE5")]

[Visual Basic .NET]
<GuidAttribute("AA4AD2AC-97B8-4d24-8E81-388A655DDBE5")> _

Assigning this GUID attribute to the class causes the class to explicitly use the GUID you have assigned. This is the GUID that will be used to register the component in COM+ services. You must also insert this into the SQL statement outlined earlier in this documentation.

  1. Add the ClassInterface attribute to your class file just under the GuidInterface attribute as in the following examples:
[C#]
[ClassInterface(ClassInterfaceType.AutoDispatch)]

[Visual Basic .NET]
<GuidAttribute("AA4AD2AC-97B8-4d24-8E81-388A655DDBE5"),
           ClassInterface(ClassInterfaceType.AutoDispatch)> _

Note that the Visual Basic .NET example simply appends the attribute to the existing GuidAttribute that is assigned to the class. The ClassInterface attribute ensures that an interface is generated by the .NET Common Language Runtime that provides access to the public members of this class for COM clients. The ClassInterfaceType is an enumeration that specifies a value for the type of class interface that gets generated.

  1. Create three public methods in the class called PostCreate, PostUpdate and PostDelete. Make sure that the signatures for each of the methods match those specified earlier in the ICRMCallout interface. This is the location where custom business logic can be created to respond to each of the events raised in Microsoft CRM. An example is provided here although your specific implementation will be different:
[C#]
public void PostCreate(int ObjectType, string ObjectId, string OrigObjectXml)
{
   FileInfo fi = new FileInfo(@"C:\CSCallout_Insert.txt");
   StreamWriter s = fi.AppendText();
   s.WriteLine("CRM Create Event Occurred...\n");
   s.WriteLine("Object Type: " + ObjectType.ToString());
   s.WriteLine("Object ID: " + ObjectId.ToString());
   s.WriteLine("Object XML String: ");
   s.WriteLine(OrigObjectXml);
   s.WriteLine();
   s.Close();
}
public void PostUpdate(int ObjectType, string ObjectId, string OrigObjectXml)
{
   FileInfo fi = new FileInfo(@"C:\CSCallout_Update.txt");
   StreamWriter s = fi.AppendText();
   s.WriteLine("CRM Update Event Occurred...\n");
   s.WriteLine("Object Type: " + ObjectType.ToString());
   s.WriteLine("Object ID: " + ObjectId.ToString());
   s.WriteLine("Object XML String: ");
   s.WriteLine(OrigObjectXml);
   s.WriteLine();
   s.Close();
}
public void PostDelete(int ObjectType, string ObjectId)
{
   FileInfo fi = new FileInfo(@"C:\CSCallout_Delete.txt");
   StreamWriter s = fi.AppendText();
   s.WriteLine("CRM Delete Event Occurred...\n");
   s.WriteLine("Object Type: " + ObjectType.ToString());
   s.WriteLine("Object ID: " + ObjectId.ToString());
   s.WriteLine();
   s.Close();
}

[Visual Basic .NET]
Sub PostCreate(ByVal ObjectType As Integer,
               ByVal ObjectID As String,
               ByVal OrigObjectXML As String)
               Implements ICRMCallout.PostCreate
        Dim fi As New FileInfo("C:\VBCallout_Insert.txt")
        ' Create the file and output some text to it
        Dim s As StreamWriter = fi.AppendText()
        s.WriteLine("CRM Create Event Occurred..." + vbNewLine)
        s.WriteLine("Object Type:" + ObjectType.ToString())
        s.WriteLine("Object ID: " + ObjectID.ToString())
        s.WriteLine("Object XML String: ")
        s.WriteLine(OrigObjectXML)
        s.WriteLine()
        s.Close()
End Sub

Sub PostUpdate(ByVal ObjectType As Integer,
               ByVal ObjectID As String,
               ByVal OrigObjectXML As String)
               Implements ICRMCallout.PostUpdate
        Dim fi As New FileInfo("C:\VBCallout_Update.txt")
        ' Create the file and output some text to it
        Dim s As StreamWriter = fi.AppendText()
        s.WriteLine("CRM Update Event Occurred..." + vbNewLine)
        s.WriteLine("Object Type:" + ObjectType.ToString())
        s.WriteLine("Object ID: " + ObjectID.ToString())
        s.WriteLine("Object XML String: ")
        s.WriteLine(OrigObjectXML)
        s.WriteLine()
        s.Close()
End Sub

Sub PostDelete(ByVal ObjectType As Integer,
               ByVal ObjectID As String)
               Implements ICRMCallout.PostDelete
        Dim fi As New FileInfo("C:\VBCallout_Delete.txt")
        ' Create the file and output some text to it
        Dim s As StreamWriter = fi.AppendText()
        s.WriteLine("CRM Delete Event Occurred..." + vbNewLine)
        s.WriteLine("Object Type:" + ObjectType.ToString())
        s.WriteLine("Object ID: " + ObjectID.ToString())
        s.WriteLine()
        s.Close()
End Sub

Note   For this specific example, a using statement (C#) or an Imports statement (Visual Basic .NET) needs to be added to the beginning of the code file that includes the System.IO namespace. For example, using System.IO; or Imports System.IO.

Generate a strong name for the assembly using the .NET Framework Strong Name Utility (sn.exe). This utility generates a public/private key file that will be incorporated into the assembly. To create this key file, go to a command prompt and change directories to the location where the solution is stored. Type in the command: sn –k callout.snk and then press Enter. This will create the key file.

  1. Add the strong file name to the assembly by adding an attribute in the AssemblyInfo code file that is part of the project. Locate the AssemblyInfo file in Solution Explorer and click it. In the code file, add the following attribute:
[C#]
[assembly: AssemblyKeyFile("..\\..\\callout.snk")]  

[Visual Basic .NET]
<Assembly: AssemblyKeyFile("..\..\callout.snk")>

This attribute looks for the strong name key file that was previously created in the folder that was created for the solution. If there is an AssemblyKeyFile attribute in the AssemblyInfo file, replace it with this one.

  1. Build the solution. You can either do this by going to the Build menu and selecting Build Solution in Visual Studio .NET or by right-clicking your project in the Solution Explorer and selecting Build.
  2. Make sure that the component is on the same machine that is hosting the Microsoft CRM application.
  3. Run the SQL statement detailed earlier in this document against the Microsoft CRM Metabase database. It is recommended that you make a backup of this database before making any modifications. You should be careful when modifying the tables outlined in this document because they are used for the Microsoft CRM Integration to Great Plains. Substitute the GUID that was assigned to the class in the GuidAttribute for the CLSIDorProgId in the SQL statement. For this sample. it looks like the following:

(@subscriberid, N’{AA4AD2AC-97B8-4d24-8E81-388A655DDBE5}’,

      N’My Sample Callout Module’, N’’)

To register the callout object to respond to a particular Microsoft CRM object’s events, the SQL statement needs to be modified to include each object type. For a complete list of object type codes, see ObjectType.

  1. Follow the instructions for registering your callout as a COM+ application as outlined earlier in this documentation. Make sure to name your COM+ application with the same name as you used in the Subscriber table in the database.

    Note   Alternately, you can go to a command prompt and type RegSvcs AssemblyName where AssemblyName is the name of your assembly. In this example, you would use RegSvcs CRMCallout.dll. This creates a COM+ application with the name specified in the ApplicationName attribute mentioned earlier, and then imports the assembly into it. Using RegSvcs.exe allows for the loading and registration of the assembly, creates a type library for the assembly, and imports that library into a COM+ application. It then uses the metadata in the DLL to properly configure the COM+ application. If you follow this step, the steps to register the component outlined earlier are not necessary. After registering the component, be sure to go into Component Services and change the account that the component runs under from the Interactive User to a specific domain account with the proper privileges. This ensures that the component will continue to operate if no one is physically logged into the server.

  2. Test the component using the Microsoft CRM application to ensure that the post-callout object responds to the Microsoft CRM object events.

© 2005 Microsoft Corporation. All rights reserved.


Show:
© 2014 Microsoft