CrmService Web Service


The CrmService Web service is the core API mechanism for programmatically interacting with all entities within Microsoft CRM. This service contains six common methods that work on all entities, and an Execute method that is available for all other needs. The service is strongly typed and WSDL compliant and will also update with any changes to the schema.

Important 

Microsoft CRM automatically updates its API interfaces as you add custom entities and custom attributes using the Web-based administration tools. Therefore, if you add multiple custom attributes to the Account entity, you will be able to reference these new attributes programmatically through the API and even with IntelliSense updates to reflect these new attributes in Visual Studio .NET.

The CrmService Web service is located at http://<crmserver>/mscrmservices/2006/crmservice.asmx.

You must add a Web reference in your Visual Studio project to programmatically access its methods. We recommend using the same naming convention that Microsoft uses for its examples, as you will see in the following procedure.

Adding a CrmService Web Reference to Your Project
  1. Open a project in Visual Studio .NET.

  2. Right-click the project and then click Add Web Reference.

  3. In the Add Web Reference dialog box, add the CrmService reference:

    1. In the URL box, type http://<crmserver>/mscrmservices/2006/crmservice.asmx.

    2. In the Web reference name box, type CrmSdk. (Note that this is case-sensitive.)

    3. Click Add Reference.

In addition, we recommend instantiating the service Url property in your code, as shown below.

 // Standard CRM Service Setup CrmService service = new CrmService(); service.Credentials = System.Net.CredentialCache.DefaultCredentials; service.Url = "http://<crmserver>/mscrmservices/2006/crmservice.asmx"; 

The Url property allows you access to the Web service URL that may be different from the URL specified in your project's Web reference. In the "Coding and Testing Tips" section of this chapter, we will explain how to use configuration settings that allow you to set the Url property of service, which allows you to deploy to different Microsoft CRM environments without having to recompile your code.

Warning 

Both the CrmService and MetadataService Web services offer a PreAuthenticate property. This property should cache the credentials of the calling user, but the Microsoft sdkreadme.htm document notes that this behavior might cause sporadic HTTP status 401: Unauthorized errors. Therefore, Microsoft recommends avoiding the PreAuthenticate property in your code at this time.

When used within the context of Web pages, code executes under the security credentials of the user browsing the Web page. At times, you might want to execute your code using different security credentials than those of the user browsing the Web page. You can change the calling user the service uses by adding the following lines of code after your standard service setup. You would replace the string of zeros (also referred to as an empty GUID) with an actual systemuserid GUID of the user whom you wish to impersonate).

 service.CallerIdValue = new CallerId(); service.CallerIdValue.CallerGuid = new Guid(""); 

Note 

The calling user will need to be part of the PrivUserGroup in Active Directory. This group is created during the installation of Microsoft CRMMicrosoft CRM will ignore an empty GUID and just use the security credentials of the user browsing the web page. If you specify a GUID that does not exist, no data will return.

Now that you have a little background on the CrmService Web Service, let's review these additional topics related to the CrmService:

  • Service naming conventions

  • Common methods

  • Execute methods

  • Request and Response classes

  • DynamicEntity class

  • Attributes

Service Naming Conventions

Microsoft CRM uses a strict naming convention for its classes, and Table 9-2 lists them for you. You can also find this information in the SDK or by using the Visual Studio IntelliSense — another excellent benefit of using a strongly typed service!

Table 9-2: Naming Conventions

Class, type, enumeration

Naming convention

Example

Core BusinessEntity names

All lowercase. This is the schema name or logical name in the metadata.

account myaccount = new account();

Custom BusinessEntity names

All lowercase with an underscore after the prefix defined in customization settings.

new_bankaccount myEntity = new new_bankaccount();

BusinessEntity attributes

All lowercase. This is the schema name or logical name in the metadata.

account.name new_bankaccount.name

Message names

Pascal case.

CreateRequest

CreateResponse

SendEmailRequest

SendEmailResponse

State enumerations

Pascal case.

Account.State

References to entity names in Fetch and QueryExpression

All lowercase. This is the schema name or_logical name in the metadata.

QueryExpression accountQE = new QueryExpression ("account"); "<fetch mapping='logical'> <entity name='account'> <all-attributes/> </entity></fetch>";

Common Methods

The following six methods provide the basic CRUD (create, read, update, delete) operations for entities, including custom entities:

  • Create Creates a new record for a given entity.

  • Retrieve Returns a single record based on the entity ID passed in.

  • RetrieveMultiple Returns multiple records based on a query expression.

  • Update Edits an existing record.

  • Delete Removes a record.

  • Fetch Returns multiple records based on a FetchXML query. The FetchXML query syntax mirrors that of Microsoft CRM versions 1.x.

Let's consider a simple example to show you how you would use one of the common methods. This example will retrieve the topic, first name, last name, and industry for a single Lead record and then display it on a Web page. We will work with the Lead record shown in Figure 9-3.

image from book
Figure 9-3: Lead form

Since this is our first SDK example, we will walk through the process of creating a basic Web application project in Visual Studio .NET 2003. We will then use and refer to this project for many of our examples in this chapter. You can also find a copy of it with our sample code download.

Creating a Web Application Project
  1. Open Visual Studio .NET 2003.

  2. On the File menu, navigate to New, and select Project.

  3. Under Project Types, select Visual C# Projects, and then click ASP.NET Web Application under Templates.

  4. In the Location box, enter http://localhost/WorkingWithCrm (assuming you have IIS installed on your development computer).

  5. Using the procedure in the previous "CrmService Web Service" section, add a Web reference to the CrmService Web service, calling it CrmSdk.

Retrieving a Lead Record from Microsoft CRM
  1. On the File menu, select Add New Item.

  2. In the resulting Add New Item dialog window, select Web Form and enter leadretrieve.aspx in the Name box.

  3. Replace the default text on the page with the code shown in Listing 9-1.

    Listing 9-1: Retrieving a Lead Record

    image from book
     <%@ Page Language="C#" %> <%@ Import Namespace="WorkingWithCrm.CrmSdk" %> <!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> <script runat="server">  protected void Page_Load(object sender, EventArgs e)  {   // Standard CRM Service Setup   CrmService service = new CrmService();   service.Credentials = System.Net.CredentialCache.DefaultCredentials;   service.Url = "http://<crmserver>/mscrmservices/2006/crmservice.asmx";   // We are using a known lead GUID. In practice, this will be passed in to your routines.   Guid leadId = new Guid("");   // Set the columns to return.   ColumnSet cols = new ColumnSet();   cols.Attributes = new string [] {"subject", "firstname", "lastname", "industrycode"};   try   {    // Retrieve the record, casting it as the correct entity.    lead oLead = (lead)service.Retrieve(EntityName.lead.ToString(), leadId, cols);    // Display the results.    // Since we have a strongly typed response, we can just access the properties of our object.    Response.Write("Topic: " + oLead.subject + "<br>");    Response.Write("First Name: " + oLead.firstname + "<br>");    Response.Write("Last Name: " + oLead.lastname + "<br>");    Response.Write("Industry: " + oLead.industrycode.Value);   }   catch (System.Web.Services.Protocols.SoapException ex)   {    // Handle error.   }  } </script> <html> <head runat="server" >  <title>Retrieve Lead</title>  <style>body { font-family:Tahoma;font-size:9pt; }</style> </head> <body>  <form  runat="server">  </form> </body> </html> 
    image from book

  4. Save your Web form page.

  5. From the Build menu, select Build Solution.

Listing 9-1 shows the Web page code for retrieving our lead record. If you were to run this sample, you would need to update the namespace of your CrmSdk reference update the path for the Url attribute.

When you add this code to your Web and execute it in Internet Explorer, you might receive the following error.

 Object reference not set to an instance of an object. Line: Response.Write(oLead.industrycode.Value); 

This error occurs because Microsoft CRM does not return an object reference for any attribute that has a value of null. We received this error because our sample Lead does not have an Industry value selected in the picklist; hence, its value is null in the database. Therefore, when your code tries to access the industrycode value property, you get an exception.

Important 

Microsoft CRM will not return a requested field if it is null in the database.

To account for the possibility that Microsoft CRM might not return a field that your code is expecting, you should ensure that the attribute you want to access is not null. This code snippet shows how to check for null values.

 Response.Write("Industry: "); if (oLead.industrycode != null)       Response.Write(oLead.industrycode.Value); 

After the code in Listing 9-1 is updated to check for a null value and refreshed, you'll receive the following output:

 Topic: Mailed an interest card back for road bikes First Name: Darren Last Name: Gehring Industry: 

The SDK contains many more examples that demonstrate how to use each of these common methods.

Execute Method

The Execute method is provided to run any special commands or business logic not available from the common methods. Unlike the common methods, the Execute method works on a Request and Response classes. You pass a request class as a parameter to the Execute method, which then processes the request and returns a response message. Though the Execute method can perform all of the actions of the common methods, its real purpose is to provide the functionality that the common methods lack. Typical actions you might use the Execute method for are retrieving the current user, assigning and routing records, and sending e-mails through Microsoft CRM. For instance, the code snippet below shows how to retrieve the current user using the Execute method.

 // Standard CRM Service Setup CrmService service = new CrmService(); service.Credentials = System.Net.CredentialCache.DefaultCredentials; service.Url = "http://<crmserver>/mscrmservices/2006/crmservice.asmx"; // Get current user object. WhoAmIRequest userRequest = new WhoAmIRequest(); WhoAmIResponse user = (WhoAmIResponse) service.Execute(userRequest); 

Note 

You must always cast the returning message to the appropriate instance of the Response class.

Request and Response Classes

Microsoft CRM uses a Request and Response message class model for the Execute method, as shown in Figure 9-4. You must create a Request class message, set the properties that you require, and pass the request a target message. You then send the request object to the platform by using the Execute method. The platform will run the request and send back an instance of a Response class message.

image from book
Figure 9-4: Request/Response model for the Execute method

Microsoft CRM Requests and Responses classes support generic, targeted, specialized, and dynamic entity requests. These request classes always end in the word Request, such as WhoAmIRequest, CreateRequest, and SendEmailRequest. Generic requests are not dependent on a specific entity and will not contain an entity name in its class name. Generic requests can work across multiple entities (such as the AssignRequest) in addition to sometimes working with no entities (such as the WhoAmIRequest).

Generic requests that apply to entities require a target message class to specify which entity should receive the action. A target class will begin with the word Target, and once instantiated and configured, it will then be applied to the target property of a generic class. This code example shows how a TargetQueuedIncident could apply to the RouteRequest to send a case to a support queue.

 // Standard CRM Service Setup CrmService service = new CrmService(); service.Credentials = System.Net.CredentialCache.DefaultCredentials; service.Url = "http://<crmserver>/mscrmservices/2006/crmservice.asmx"; // Create the Target object (case or incident for this example) TargetQueuedIncident target = new TargetQueuedIncident(); // EntityId is the Guid of the case record being routed // We are using a known case GUID. In practice, this will be passed in to your routines. target.EntityId = new Guid(""); // Request object RouteRequest route = new RouteRequest(); route.Target = target; route.RouteType = RouteType.Queue; // EndPointId is the GUID of a non-work  in progress queue or user the case is being routed to. // We are using a known case GUID. In practice, this will be passed in to your routines. route.EndpointId = new Guid(""); // SourceQueueId is the Guid of the queue the case is coming from // We are using a known case GUID. In practice, this will be passed in to your routines. route.SourceQueueId = new Guid(""); try {  // Execute the Request  RouteResponse routed = (RouteResponse)service.Execute(route); } catch(System.Web.Services.Protocols.SoapException ex) {  // Handle error. } 

Specialized requests are similar to targeted requests except that they work only on a specific entity to perform a distinct action. Their naming convention will always be <Action><EntityName>Request. Good examples of these requests are the SendEmailRequest or the LoseOpportunityRequest.

The dynamic entity request permits you to use requests at runtime for any entity. By setting the parameter ReturnDynamicEntities to True, your results will be returned as a DynamicEntity class instead of the BusinessEntity class. Not all requests permit the DynamicEntity option, and you should refer to the SDK for the complete list. We will go into more detail about the DynamicEntity class next.

DynamicEntity Class

The DynamicEntity class, derived from the BusinessEntity class, provides runtime access to entities and attributes even if those entities and attributes did not exist when you compiled your assembly. The DynamicEntity class contains the logical name of the entity and a property-bag array of the system attributes. In programming terms, this can be thought of as using a variant for a variable type. The class allows you to access entities and attributes created in Microsoft CRM, even though you may not have the actual entity definition from the WSDL.

The DynamicEntity class must be used with the Execute method, and it contains the following properties:

  • Name Sets the entity schema name

  • Properties Array of type Property (which is a name/value pair)

Let's review the syntax of the DynamicEntity class to create a Lead. We will create a string property to store our subject text, which we will pass into the DynamicEntitydynLead object. After we create our DynamicEntity object and set its name to lead, we create the TargetCreateDynamic class to serve as our target message for the CreateRequest call. Note that we must explicitly set the owner for the DynamicEntity, because it is not assumed.

 // Standard CRM Service Setup CrmService service = new CrmService(); service.Credentials = System.Net.CredentialCache.DefaultCredentials; service.Url = "http://<crmserver>/mscrmservices/2006/crmservice.asmx"; // Get current user ID. WhoAmIRequest userRequest = new WhoAmIRequest(); WhoAmIResponse user = (WhoAmIResponse) service.Execute(userRequest); // Set up dynamic entity. DynamicEntity dynLead = new DynamicEntity(); // Set entity name and specify array of properties. dynLead.Name = "lead"; dynLead.Properties = new Property[] { CreateStringProperty("subject","New Lead Using Dynamic Entities"), CreateStringProperty("lastname","Steen"), CreateStringProperty("firstname","Heidi"), CreateOwnerProperty(user.UserId), }; // Standard target request, passing in the dynamic entity. TargetCreateDynamic target = new TargetCreateDynamic(); target.Entity = dynLead; CreateRequest create = new CreateRequest(); create.Target = target; CreateResponse response = (CreateResponse)service.Execute(create); // Helper method that creates a string property based on passed-in values private Property CreateStringProperty(string Name, string Value) {  StringProperty prop = new StringProperty();  prop.Name = Name;  prop.Value = Value;  return prop; } // Helper method that creates an owner property based on a passed-in GUID private Property CreateOwnerProperty(Guid UserId) {  Owner ownerid = new Owner();  ownerid.Value = UserId;  ownerid.type = EntityName.systemuser.ToString();;  OwnerProperty prop = new OwnerProperty();  prop.Name = "ownerid";  prop.Value = ownerid;  return prop; } 

Obviously, you would not use the dynamic entity approach to create a Lead record, because it's not as efficient and it requires more code. However, Microsoft CRM provides this class for run-time situations in which you might not know the entity or for when you want to add new attributes to an existing entity. You will see that this class is extremely handy when you want to deserialize unknown XML into an entity class, as we will demonstrate in our Data Auditing example in the "Sample Code" section later in this chapter.

We also want to mention the helper methods, shown in this example, which we use for creating the properties that we want to set. In this particular example, we know that we are working with string and owner properties, but in some scenarios, you might not know the property type. To address this, you must query the metabase and determine the data types of your desired attributes at run time. Microsoft CRM allows you to do this with the MetadataService Web service, as you will see shortly.

Attributes

In earlier versions of Microsoft CRM, you passed all attributes to the API methods as strings. However, Microsoft CRM 3.0 API uses strongly typed classes, so you must create typed attributes when setting values for an entity. The SDK documentation lists examples of each type and how to use them, so we won't list them here. However, you will see examples of this throughout our sample code.




Working with Microsoft Dynamics CRM 3.0
Working with Microsoft Dynamics(TM) CRM 3.0
ISBN: 0735622590
EAN: 2147483647
Year: 2006
Pages: 120

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net