Click here to Skip to main content
15,886,963 members
Articles / Programming Languages / C#

Writing Microsoft CRM 3.0 Callouts – Sample Code: Turkish Citizen Number Validator

Rate me:
Please Sign up or sign in to vote.
3.80/5 (7 votes)
29 Aug 2023CPOL9 min read 53.5K   223   9   6
This article focuses on callout development for MS CRM 3.0. As an example Turkish Citizen Number Validator code is written.
In this article, I try to explain the basic concepts to a novice MS CRM developer who wants to customize Microsoft CRM 3.0. This article consists of external references and code samples that are provided with the permission of the copyright holders' permission.

Screenshot - image002.jpg

Introduction

In this article, I will try to explain the basic concepts to a novice Microsoft CRM developer who wants to customize Microsoft CRM 3.0. This article consists of external references and code samples that are provided with the permission of the copyright holders' permission. If you get quotations from this article, please provide the original link as the reference info in your material. Outline is as follows:

  • What is a callout? Where are they used?
  • Which events trigger callouts?
  • A simple case example: Validator for Turkish Citizen Number (=TCKN)

Background

Having a strong C# programming knowledge is an asset to benefit from this article. First, I will try to explain basic concepts for callout programming for MS CRM 3.0.

What are Callouts?

Callouts are simply class libraries that are compiled using .NET Framework (=fw) 1.1.

The first question in our minds is: Can we write callouts using fw2.0 or fw3.0?

Unfortunately NO! Since MS CRM 3.0 is written using fw 1.1 and callout assemblies are loaded in the same application pool with CRM, there is a limitation in executing only one framework in one application pool (=app pool), CRM application pool uses fw1.1 and you cannot load an assembly that requires fw2.0 or above in that app pool. So we have to compile our callout code in fw1.1.

How to Generate fw1.1 Code?

There are two ways to generate fw1.1 code.

First is the conventional way, we use Visual Studio.NET (=VSNET) 2003. We write our code in the IDE and hit F5 to generate the compiled code.

Second is a bit complicated, you may utilize VSNET 2005 and fw1.1 to generate fw1.1 assemblies. However, this technique requires msbee setup and has a proper config file. Then, you only need to write an msbuild command in the VSNET command prompt to generate fw1.1 assembly.

Hence, this is a bit more complicated. I will explain the issue in another article.

Callouts are used to extend MS CRM 3.0 features. Mostly in integration projects, callouts are used to provide data integrity, and consistence. For instance, you don't want to save two people having the same employee number, however by default MS CRM allows having two records with the same employee number. Just at this point, you may write a callout and it checks the existence of the employee number, if that number exists, aborts the save process, otherwise makes the process continue the usual way.

Importance of CrmCalloutBase Class

This class resides in the microsoft.crm.platform.callout.base.dll file which is located in the system folder of the Microsoft Crm 3.0 installation directory. This is the main starting point for the callout developer, that is:

Quote:

All the callouts must be derived from the CrmCalloutBase class, thus you have to reference microsoft.crm.platform.callout.base.dll file all of your callout projects. This dll file may be found at the MS CRM 3.0 installation CD's following path:

[Microsoft CRM 3.0 PATH]\Bin\Assembly\Microsoft.Crm.Platform.Callout.Base.dll

Here, we see the events that fire callouts. Using these events, MS CRM custom checks and additional functionalities are achieved.

PreAssign / PostAssign Specifies a method called before / after an assign operation
PreDelete / PostDelete Specifies a method called before / after a delete operation
PreUpdate / PostUpdate Specifies a method called before / after an update operation
PreCreate / PostCreate Specifies a method called before /after a create operation
PreMerge / PostMerge Specifies a method called before / after a merge operation
PreSetState / PostSetState Specifies a method called before / after a set state operation
PreSend Specifies a method called before a send e-mail operation
PostDeliver Specifies a method called after a deliver e-mail operation
Reference: http://msdn2.microsoft.com/en-us/library/aa613520.aspx

The above table describes the types of operations can be handled using callouts. We may fully customize Create/Update /Delete/Assign operations by writing pre and post callout methods. Since names describe the usages of the methods, some of them need explanation.

The Assign event occurs when an entity's owner is changed. The SetState event occurs when an entity's state is changed to active or inactive. See Apprendix A1 for a sample code about this event.

By deriving from CrmCalloutBase class and implementing one of the above methods, we write our callout code, then we compile it to a DLL file. Now it's time to deploy the resultant assembly to the MS CRM server.

.NET assembly (the class library) is put in the MS CRM server's installation directory's sub folder bin\assembly, i.e., if you installed the server to C:\Program Files\Microsoft CRM then the callout assembly must be put to C:\Program Files\Microsoft CRM\Server\bin\assembly.

Quote:

Assuming the CRM installation directory is C:\Program Files\Microsoft CRM\
All the callouts must reside at
C:\Program Files\Microsoft CRM\Server\bin\assembly\

After putting the callout DLL to the assembly directory, callout declaration must be made to the CRM server, otherwise server cannot know when to call the callout assembly. Notifying the server about callouts is done using the callout.config.xml file that is found in the assembly directory of the CRM.

XML
<?xml version="1.0" encoding="utf-8" ?>
<callout.config version="2.0">
    <callout entity="contact" event="PreCreate">
        <subscription assembly="DontPermitDuplicates.dll" 
                      class="DontPermitDuplicates.NoDblNames" />
    </callout>
</callout.config>

Above, we see a callout assembly notification to CRM. Callout class library's namespace is called DontPermitDuplicates. Just before a Lead entity is created in the CRM, this callout is called.

CRM instantiates an object of the DontPermitDuplicates.NoDblNames class. Then executes the PreCreate method in that class. That method may check things or do the required custom business operations, then object may either abort the creation operation by raising an error message, or makes the operation continue so the entity is created in the CRM.

Step by Step Simple Callout Example

  1. Create a Class Library project in VSNET 2003.
  2. Add reference to microsoft.crm.platform.callout.base.dll file.
  3. Derive a class from CrmCalloutBase.
  4. Write PreCreate and then CTRL+SPACE to see the method signature find PreCreate method and press enter.

Use the following sample code to achieve your first callout code.

C#
public override PreCalloutReturnValue PreCreate(
    CalloutUserContext userContext,
    CalloutEntityContext entityContext,
    ref string entityXml,
    ref string errorMessage)
{
    PreCalloutReturnValue calloutRetVal = PreCalloutReturnValue.Continue;

    // error message is not set at the beginning errorMessage = string.Empty;
    XmlDocument xd = new XmlDocument();
    xd.LoadXml(entityXml);

    /* all the elements in the XML file is iterated, 
       and only desired ones are added to the nvPostedInfo collection */
    NameValueCollection nvPostedInfo = new NameValueCollection();
    foreach (XmlElement element in xd.GetElementsByTagName("Property"))
    {
        string strAttributeName = element.Attributes.GetNamedItem("Name").Value;
        switch (strAttributeName)
        {
            case "tbs_tckn":
                nvPostedInfo.Add("tbs_tckn", element.InnerText);
                break;
        }
    }

    if (!IsTcknValid(nvPostedInfo["tbs_tckn"]))
    {
        errorMessage = "The TCKN value is not valid!";

        calloutRetVal = PreCalloutReturnValue.Abort;
        // abort operation }
        return calloutRetVal;
    }
}

The above code contains a method called IsTcknValid. This method returns a boolean value, whether the parameter of the method is a valid TCKN (=Republic of Turkey Citizen Number) value.

Below, we see the TCKN checker code block. This is very useful to preserve the data validity. (The code presented is a port of the SQL function that is located at following URL:
http://www.verivizyon.com/detail.asp?catid=17&cid=317 )

C#
private bool IsTcknValid(string TcknToValidate)
{
    bool isValid = false;
    TcknToValidate = TcknToValidate.Trim();
    if (TcknToValidate.Length != 11) return isValid;
    short C1, C2, C3, C4, C5, C6, C7, C8, C9;
    int Q1, Q2;
    Int64 TCNO = Convert.ToInt64(TcknToValidate);
    Int64 ATCNO = TCNO / 100;
    Int64 BTCNO = TCNO / 100;
    C1 = Convert.ToInt16(ATCNO % 10); ATCNO /= 10;
    C2 = Convert.ToInt16(ATCNO % 10); ATCNO /= 10;
    C3 = Convert.ToInt16(ATCNO % 10); ATCNO /= 10;
    C4 = Convert.ToInt16(ATCNO % 10); ATCNO /= 10;
    C5 = Convert.ToInt16(ATCNO % 10); ATCNO /= 10;
    C6 = Convert.ToInt16(ATCNO % 10); ATCNO /= 10;
    C7 = Convert.ToInt16(ATCNO % 10); ATCNO /= 10;
    C8 = Convert.ToInt16(ATCNO % 10); ATCNO /= 10;
    C9 = Convert.ToInt16(ATCNO % 10); ATCNO /= 10;
    Q1 = ((10 - ((((C1 + C3 + C5 + C7 + C9) * 3) + (C2 + C4 + C6 + C8)) % 10)) % 10);
    Q2 = ((10 - (((((C2 + C4 + C6 + C8) + Q1) * 3) + 
          (C1 + C3 + C5 + C7 + C9)) % 10)) % 10);
    if (TCNO == ((BTCNO * 100) + (Q1 * 10) + Q2))
    {
        isValid = true;
    }
    return isValid;
}

After writing the above code to a class library project, we have to compile it and then the resultant DLL file must be copied to the MS CRM's Callout directory that is: C:\Program Files\Microsoft CRM 3.0\Server\bin\assembly. This directory has a callout.config file which contains the executed callout DLLs for every entity that needs to be checked.

We add the following line of codes in the callout.config.xml file in order to test our callout.

XML
<?xml version="1.0" encoding="utf-8" ?>
<callout.config version="2.0">
    <callout entity="contact" event="PreCreate">
	    <subscription assembly="DontPermitDuplicates.dll" 
         class="DontPermitDuplicates.NoDblNames" />
	</callout>
</callout.config>

ATTENTION! Don't forget to put the XML extension to the callout.config file, i.e., callout.config.xml.

Now we have to test it using a valid and an invalid TCKN value.

Testing the Code

First, we have to create an attribute that will hold the citizen number, the attribute will be called new_tckn. After creation, a field will be placed on the contact's form.

  1. Create the attribute for the contact entity.
  2. Place the field on the contact form, then publish the changes.
  3. Edit the following file, if it does not exist, then create it using Notepad.

    C:\Program Files\Microsoft CRM\Server\bin\assembly\callout.config.xml

  4. Make IIS start again by doing Start > Run > "iisreset"

Now try to enter 12345678901 value for the tckn field of a new contact record. This operation will be aborted by the callout since the value is not a valid TCKN number.

Screenshot - image005.gif

Conclusion

In this article, the basics of callout programming are shown. As an example of a simple callout, a Turkish Citizen Number validator callout is developed and tested. Since callout assemblies are loaded and run by the MS CRM application using reflection, we have to generate .NET Framework 1.1 assemblies for our callouts. That is because MS CRM 3.0 is implemented using .NET 1.1 Framework. As a restriction, .NET 1.1 processes cannot execute any higher version of the framework assemblies in their application domain.

In our example, there were no connection strings in assembly. Since we don't want to keep our connection string hard coded, we need to store them in a config file, thus the config file must be the web.Config of the MS CRM application.

For the curious reader, it is beneficial to mention that callouts' DataAccessLayer may be implemented using Enterprise Library's Data Application Block. Until next article, keep coding!

Appendix – Additional Remarks

A.1. When your callouts do not work, check out here!

Well written two troubleshooting articles may be found at the following locations:

A.2. Other Callout Resources

A.3. Enterprise Library for .NET Framework 1.1

Source: http://msdn2.microsoft.com/en-us/library/ms954827.aspx

This page provides an overview of the Enterprise Library Data Access Application Block. This is reusable and extensible source code-based guidance that simplifies development of common data access functionality in .NET-based applications.

Downloads

License End User Licensing Agreement (EULA)
Hands-On Labs Enterprise Library - Hands on Labs
Webcast Enterprise Library Data Access Application Block (Level 300)
Community Enterprise Library Community

System Requirements for Enterprise Library for .NET Framework 1.1

  • Supported OS: Windows 2000; Windows Server 2003; Windows XP Professional Edition
  • Microsoft .NET Framework version 1.1
  • Microsoft Visual Studio .NET 2003 development system (Enterprise Architect, Enterprise Developer, or Professional edition)
  • Some blocks and samples require the use of Microsoft SQL Server or other database products.
  • NUnit 2.1.4 is required if you want to execute unit tests.

A.4 Sample List of files in Callout Assembly Directory

Screenshot - image007.gif

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Turkey Turkey
As an e-commerce consultant, has been working in IT industry since 2003, has worked on Microsoft Commerce Server, Microsoft CRM, and Microsoft Sharepoint Server.

He is interested in Artificial Intelligence (AI) and Robotics. However doing some research and reading about them are just hobbies, and is not part of his professional life.

As an application of AI in E-Commerce and CRM area he is interested in Business Intelligence concepts such as data mining, and practical implementations of artificial neural networks. He likes to read articles about latest C# development and design patterns.

His spare time activities are cycling and dancing.

Comments and Discussions

 
General...Interesting article Pin
matply22-Apr-10 8:27
matply22-Apr-10 8:27 
Generalfields content not preserved Pin
lemravec28-Apr-08 23:13
lemravec28-Apr-08 23:13 
GeneralMy Callout is not working??? :&lt;&lt;/codeProject$$&gt; Pin
qumer10131-Dec-07 3:27
qumer10131-Dec-07 3:27 
Generalgreat article Pin
YogiMySon18-Oct-07 15:41
YogiMySon18-Oct-07 15:41 
QuestionPostSetState not working. Pin
Kuntal Ghoshal6-Jun-07 2:59
Kuntal Ghoshal6-Jun-07 2:59 
AnswerRe: PostSetState not working. Pin
Alen M20-Oct-07 3:53
Alen M20-Oct-07 3:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.