Building applications for Partner hosted CRM

Earlier this year, we announced a new program to enable service providers offer hosted version of Microsoft Dynamics CRM 3.0. The partner hosted version of CRM which is based on a Service Provider Licensing Agreement (SPLA) model delivers the same rich set of user interface options as offered by the on-premise version of Microsoft CRM as well as flexible deployment options for deploying all or parts of a Microsoft CRM solution as an on-premise or hosted application and Extensive configuration, extensibility and customization capabilities.

This article shows the basic concepts around building a simple application using the web service APIs of the hosted version of CRM. Since all of the CRM rich web service APIs are available on our hosted version, ISVs and partners are able to build powerful Service Oriented applications and mashups through accessing these APIs over the internet.

The application retrieves a list of user tasks that are active (open) enabling the user to see their tasks in any type of application that is capable of making a web service call into the hosted CRM APIs. I used Visual Studio 2005 and ASP.NET 2.0 to build the application. In order to demo the application, I used the trial version of Streamline solutions, one of our service providers (check out their site to find out how to sign up for a hosted version of CRM). Streamline provides a demo environment where you can try CRM application and web services APIs. I highly recommend that you check it out.

The following diagram shows how the custom application accesses the hosted CRM web services APIs over the internet.

 

 

 

Authentication

The first step to access the CRM web services is to get authenticated. Partner hosted version of CRM provides a form based authentication method over Secure Socket Layer(SSL) protocol to authentic the CRM users. This is the first step to start using the application. I used a simple ASP.NET 2.0 login control to capture the user name and password. I then send the user name and password to the CRM web service APIs that is hosted on the Streamline servers.

 

 

CRM validates the user name and password and if authenticated, returns a security cookie. The following code shows how to use HttpWebRequest to obtain a cookie from the hosted CRM.

 

    //Get a CRM cookie before accessing the CRM web services

    public Cookie TryConnect(string url, string userName, string password)

    {

        // Get the remote server URL

      Uri serverUri = new Uri(url);

        Uri logonServerUri = new Uri(serverUri, @"LogonServer/Logon.aspx");

        // Add HTTP parameters to pass credentials

        string encodedUserName = HttpUtility.UrlEncode(userName);

        string encodedPassword = HttpUtility.UrlEncode(password);

        string logonServerUrl = String.Format(CultureInfo.InvariantCulture, "{0}?UserName={1}&Password={2}", logonServerUri.ToString(), encodedUserName, encodedPassword);

        // Make a web request that does not allow redirection

        HttpWebRequest logonRequest = (HttpWebRequest)WebRequest.Create(logonServerUrl);

        logonRequest.AllowAutoRedirect = false;

        logonRequest.CookieContainer = new CookieContainer();

   HttpWebResponse logonResponse = (HttpWebResponse)logonRequest.GetResponse();

        Cookie authCookie = null;

     

        using (logonResponse)

        {

            if (HttpStatusCode.Found != logonResponse.StatusCode)

            {

             // throw new CrmException(logonServerUrl, ErrorCodes.InvalidOperation);

            }

            if (null == (authCookie = logonResponse.Cookies["CRMAuthCookie"]))

            {

                // throw new CrmException(logonServerUrl, ErrorCodes.InvalidOperation);

            }

        }

        // Now we have the cookie, make sure the credential is valid by passing the cookie back to CRM

        logonRequest = (HttpWebRequest)WebRequest.Create(serverUri);

        // The following user agent is required by CRM

        logonRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2)";

        logonRequest.AllowAutoRedirect = false;

        logonRequest.CookieContainer = new CookieContainer();

        logonRequest.CookieContainer.Add(authCookie);

        logonResponse = (HttpWebResponse)logonRequest.GetResponse();

        using (logonResponse)

        {

            if (HttpStatusCode.OK != logonResponse.StatusCode)

            {

               throw new InvalidOperationException(logonServerUrl);

            }

        }

        return (authCookie);

    }

The next step is to use the returned cookie in the soap header of my CRM web service proxy. I do that by adding the cookie to the CookieContainer property of my web service proxy. The web service proxy was generated for me when I added CRM Web service WSDL to my Visual Studio project.

//Connect to hosted CRM web services using the cookie

public SPLACRMConnect(string uname, string pword)

{

        username = uname;

        password = pword;

        

       

        //Get a cookie based on user name and password

        Cookie myC = TryConnect(HostedCRMURL, username, password);

       

        //Setup proxy to access CRM Web Service

        mySVC = new CrmService();

        mySVC.Url = HostedCRMURL + "/mscrmservices/2006/crmservice.asmx";

        mySVC.CookieContainer = new CookieContainer();

        mySVC.CookieContainer.Add(myC);

        //Setup proxy to access CRM Metadata Web Service

        myMetadataSVC = new MetadataService();

        myMetadataSVC.Url = HostedCRMURL

        +"/mscrmservices/2006/metadataservice.asmx";

        myMetadataSVC.CookieContainer = new CookieContainer();

        myMetadataSVC.CookieContainer.Add(myC);

}

Call Web Service APIs

Now I am ready to call CRM web services. I simply query CRM web services using QueryByAttribute. This class is a simple subset of QueryExpression class that enables building simple queieries. Of course you can use QueryExpression to build much more complex queries. Both of these classes are available in our WSDL and fully document in our SDK docs.

    //Get a list of tasks from Hosted CRM web services

    public IEnumerable GetDataSource()

    {

        // Connect to CRM and execute a standard query that will return a collection

        // of task records.

        WhoAmIRequest myW = new WhoAmIRequest();

        WhoAmIResponse myWRes = new WhoAmIResponse();

        myWRes = (WhoAmIResponse)mySVC.Execute(myW);

              

        QueryByAttribute query = new QueryByAttribute();

        query.EntityName = EntityName.task.ToString();

        ColumnSet cs = new ColumnSet();

       

        //List of columns to show in the Grid

        cs.Attributes = new string[] { "ownerid", "description","regardingobjectid", "subject", "statecode"};

        query.ColumnSet = cs;

      

        //Only get the open tasks owned by this user

        query.Attributes = new string[] { "ownerid", "statecode" };

        query.Values = new object[] { myWRes.UserId , 0};

        RetrieveMultipleRequest rm = new RetrieveMultipleRequest();

        rm.Query = query;

        rm.ReturnDynamicEntities = true; // The UniversalEntityList only supports dynamic entities

        RetrieveMultipleResponse rmOut = (RetrieveMultipleResponse) mySVC.Execute(rm);

       

        //Bind the data retrieved from CRM web services to a data source object that can be used as the grid data source

        _data = new UniversalEntityList(rmOut.BusinessEntityCollection, username, password);

        return _data;

    }

 

Databinding to grid

Now I have a list of my open tasks retrieved from CRM, I need to show them to the user. I used a standard ASP.NET 2.0 GridView control and one of the SDK samples to bind the CRM data to the Grid (you can find the grid data binding sample in <CRM SDK Folder>\sdk samples\fullsample\databinding folder). The Here is the data that is returned from Streamline servers to a grid page that I am running locally on my machine.

 

 

Download the source code and build your own app

I have attached the zipped version of Visual Studio 2005 project files for this application to this post (CRMSPLASample.zip) so you can download and try it yourself. You need Visual Studio 2005 and a hosted CRM server in order to try and use this application. Unzip the files into a virtual directory on your web server and open the solution page in VS. Change the server URL to point to the hosted CRM service that you want to target. After you have complied the project.

Note: the project includes the URL to Streamline trial hosted CRM environment. It is entirely up to Streamline to keep or disable web services access to their trial environment.

CRMSPLASample.zip