Using Microsoft Dynamics CRM 4.0 as a Development Platform

icrosoft has significantly enhanced the capabilities of Microsoft Dynamics CRM to not only simplify customization, but also to allow developers to use it as a development platform and build custom solutions.

Microsoft Dynamics CRM 4.0 Web Services

Microsoft Dynamics CRM 4.0 (MS CRM) exposes a set of SOAP-based APIs that provide access to the core CRM data model and business objects so developers can leverage existing MS CRM functionality in their custom CRM solutions. The services support both object-based and role-based security, which allows the core model to be exposed in a secure fashion.

The following web services are exposed by the Microsoft Dynamics CRM 4.0 SDK:

  • CRM Discovery Service. A single instance of MS CRM server can host multiple organizations and each organization has a CRM Service associated with it. This service helps you identify the CRM Service endpoint for your organization.
  • CRM Service. This is the primary MS CRM service that is used to access CRM entity instances. The CRM Service methods also support offline function.
  • CRM Metadata Service. This service allows access to the CRM entity, attribute and relationship definitions of your organization.
Author’s Note: The web services exposed by Microsoft Dynamics CRM 4.0 SDK are compliant with WSI Basic Profile 1.1. This makes the services interoperable with non-Microsoft platforms.

In this article you will see how these web services allow developers to leverage MS CRM as a development platform to create configurable CRM entity web parts for an ASP.NET application. You’ll also see how third-party applications can consume MS CRM data using an example web part that displays weather information based on the user’s MS CRM Contact Entity zip code.

What You Need
  • Basic understanding of Microsoft Dynamics CRM 4.0
  • Understanding of ASP.NET web part framework
  • Partner ID and license key from weather.com to subscribe to the weather data

ASP.NET 2.0 provides a very flexible web part infrastructure suitable for building dashboard style views for business data. The example project in this article uses that infrastructure to provide a dashboard view of MS CRM contact and account information, allowing users to configure the entity fields that the dashboards display by exposing them as web part properties.

Building a CRM Helper Class

In this section you will see how to construct a CRMHelper class that acts as a wrapper for the CrmService.

Step 1. Add a Service Reference.

In your web application project (named CRMWebParts in this example), right-click on References and click “Add Web Reference.” In the Add Web Reference dialog, search for web services on your local machine. Find the CrmService instance, and click on the service link (see Figure 1). In the web reference name field, specify the name of the service as CrmSdk.

 
Figure 1. Add Web Reference Dialog: Displays the list of web services available in the local system. Locate the CrmService and add the reference to your project.
Author’s Note: There are two versions of the CrmService; one is a backwardly compatible version. Make sure you reference the right version. The URL for the Microsoft Dynamics CRM 4.0 version looks something like http:///mscrmservices/2007/crmservice.asmx.

Step 2. Create a CRM Service Instance

You need to create an instance of the CRMService to work with it, as shown below:

public static CrmService CrmWebService{   get   {      if (null == m_crmService)      {         CrmSdk.CrmAuthenticationToken token = new             CrmSdk.CrmAuthenticationToken();         token.OrganizationName = onfigurationManager.AppSettings[            "OrganizationName"];         token.AuthenticationType = 0;         m_crmService = new CrmService();         m_crmService.Url = ConfigurationManager.AppSettings[            "CrmSdk.CrmServiceWsdl"];         m_crmService.CrmAuthenticationTokenValue = token;         m_crmService.Credentials = new NetworkCredential(            ConfigurationManager.AppSettings["UserName"],            ConfigurationManager.AppSettings["Password"],            ConfigurationManager.AppSettings["Domain"]);      }      return m_crmService;   }}

The preceding code creates a static property called CrmWebService that returns a singleton instance of CrmService. The CrmService is configured for security and accepts the credentials of the logged in user. A real-world application would assign the credentials using System.Net.CredentialCache.DefaultCredentials, but for demonstration purposes the preceding code assumes the user has administrator rights.

Step 3. Create Data-Retrieval Helper Methods

Now you can use the CrmService instance methods to fetch data dynamically in the form of BusinessEntity objects.

BusinessEntity is an abstract class that encompasses all MS CRM entities, which gives you considerable flexibility when fetching MS CRM entity data. Specifically, you can use the class to write generic methods that have no entity type requirements to return records based on dynamic queries.

In addition to methods for basic CRUD operations, the CrmService exposes two other methods:

  1. RetrieveMultiple. Used to retrieve results from a custom query that can contain conditions, filter expressions and link entities.
  2. Fetch. Used to retrieve results from a custom query in XML format.
  3. Author’s Note: The CrmService also has an Execute method that can perform all the above operations, but the individual methods are much faster, so you should use those whenever possible.

The following code illustrates the use of RetrieveMutiple:

public static BusinessEntity[] GetRecordsByEntity(string    entityName, string[] columnSet){   QueryExpression expression = new QueryExpression();   expression.EntityName = entityName;   ColumnSet columns = new ColumnSet();   columns.Attributes = columnSet;   expression.ColumnSet = columns;   BusinessEntityCollection entities =       CrmWebService.RetrieveMultiple(expression);   if (entities.BusinessEntities.Length > 0)      return entities.BusinessEntities;   return null;}

The GetRecordsByEntity method returns an array of dynamic entity records by entity name (the contacts in this example). You can choose to return all columns or specify the list of columns to return.

The CRMHelper class needs some additional helper methods to fulfill the design requirements. For this article, the class needs the following additional methods:

  1. GetRecordByEntityId. This is an overloaded method that returns a specific entity record. The contact web part uses this method to populate the contact information. Contact is also a link entity for account. To fetch the account information for the contact and populate the account web part you can create an overloaded form of the method as shown below:
  2. public static BusinessEntity GetRecordByEntityId(   string entityName, string linkEntityName,    string entityAttribute, string linkEntityAttribute,    Guid linkEntityId){   ConditionExpression condition = new ConditionExpression();   condition.AttributeName = linkEntityAttribute;   condition.Operator = ConditionOperator.Equal;   condition.Values = new object[] { linkEntityId.ToString() };            LinkEntity link = new LinkEntity();   link.LinkCriteria = new FilterExpression();   link.LinkCriteria.FilterOperator = LogicalOperator.And;   link.LinkCriteria.Conditions = new ConditionExpression[] {       condition };   link.LinkFromEntityName = entityName;   link.LinkFromAttributeName = entityAttribute;   link.LinkToEntityName = linkEntityName;   link.LinkToAttributeName = entityAttribute;            QueryExpression expression = new QueryExpression();   expression.EntityName = entityName;   expression.ColumnSet = new AllColumns();   expression.LinkEntities = new LinkEntity[] {link};   BusinessEntityCollection entities =       CrmWebService.RetrieveMultiple(expression);   if (entities.BusinessEntities.Length > 0)      return entities.BusinessEntities[0];            return null;}

    As you can see, the QueryExpression for this method accepts a LinkEntity, so the example will specify which contact should be the link entity for account.

  3. GetValueFromProperty. In this example the entity web parts have configurable properties where users can specify the fields that they want to display for the entities. This method takes the property name as a parameter along with the BusinessEntity and returns the value of the property by dynamically looping through the list of properties available for the entity until it finds a match. Listing 1 shows the method implementation.

Creating MS CRM Entity Web Parts

Before creating the entity web parts you need to create the ASP.NET personalization database that stores the web part configuration information. At the Visual Studio command prompt, execute the aspnet_regsql command. Follow the steps in the wizard to create a personalization database.

With the personalization database in place, you’re ready to create the web parts. First, note the web parts folder in the CRMWebParts application, which has two user controls named ContactWebPart and AccountWebPart. The user controls inherit from the WebPartBase class, which implements the IWebPart interface. The following code shows a sample property exposed to the editor part that a user can set when the site is running in edit mode:

[Personalizable(PersonalizationScope.User),   WebBrowsable, WebDisplayName("Account Field 1"),   WebDescription("Enter the Field Name")]public string Field1{   get { return _field1; }   set { _field1 = value; }}

 
Figure 2. Displaying Web Part Properties in the Editor Zone: Specify the entity properties that you want to display in the web part.

The WebBrowsable attribute allows the property to be displayed in the property editor. In the Default.aspx page add three web part zones, and then add the ContactWebPart and AccountWebPart user controls to the left and center zone templates respectively. Run the site in edit mode and click edit on the web part menu to display the property editor (see Figure 2).

In the editor zone, you can specify which entity properties that you want the application to display to web part users. This example supports only three properties per web part, but you can expose more fields to display additional entity properties. You can find a list of entity property names in the SampleProperties.txt file. The configuration information gets saved in the personalization database so it will be available the next time you run the page. Add the following code in the Default.aspx page Page_Load event handler to populate the entity web parts with the data retrieved from the CrmWebservice:

if(!string.IsNullOrEmpty(Request.QueryString["contactId"])){   CrmSdk.contact entity =       CRMHelper.GetRecordByEntityId(      "contact", new Guid(Request.QueryString["contactId"]))       as CrmSdk.contact;   ContactWebPart1.SetFieldValues(entity);               CrmSdk.account linkEntity = CRMHelper.GetRecordByEntityId(      "account", "contact", "accountid", "contactid",       new Guid(Request.QueryString["contactId"]))       as CrmSdk.account;   AccountWebPart1.SetFieldValues(linkEntity);}

The preceding code accepts a contactId as a query string, and then calls the CRMHelper methods to fetch the contact and account information from MS CRM. It then populates the web parts with the retrieved data using the SetFieldValues method exposed by the AccountWebPart and ContactWebPart user controls. The SetFieldValues method assigns values to the configured properties by dynamically looking for the property information in the BusinessEntity.

The CRMWebParts web application contains a SearchContacts.aspx page that displays all the contacts available in your organization in a DataList. Double-clicking on a contact row redirects to the Default.aspx page with the contactId of the selected contact appended as a query string.

The next step show how external applications can consume MS CRM Data. To demonstrate this, the weather web part in the CRMWebParts web application uses the zip code for a contact or account to display the weather for that location.

Place the WeatherWebPart user control in the right web part zone of the Default.aspx page. The page calls the SetZipCode method, which sets the location of the Weather control based on the zip code returned by the entity record. Figure 3 shows how the default page looks after you double-click on a contact record in the SearchContacts page.

 
Figure 3. Zip Code-Based Weather: Double-clicking a contact in the SearchContacts page displays a weather report based on that entity record’s location.
Author’s Note: You must add a reference to the anrControls.Weather.dll assembly for the weather control to work. The weather control itself was written by Milan Negovan, and you can find detailed information about it in his Weather Custom Server Control article.

As you can see, the ability to call MS CRM web services opens up enormous opportunities for using it as a development platform. This example showed how to build a simple configurable dashboard view on Entity data using CrmService, but you could easily extend the application by providing data-editing capabilities so users could access and manipulate MS CRM entity metadata. It’s worth noting that the CrmService is also available in offline mode, so you can build applications that support offline scenarios.

For more information on using MS CRM as a development platform, see the “Developing Custom Solutions” section of the Microsoft Dynamics CRM 4.0 SDK. Visit the Microsoft Dynamics CRM Home page for updated information on MS CRM. Finally, you can find more information about the weather service here.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Related Posts