Arash Ghanaie-Sichanie Blog

Microsoft, Program Management, Live Services, Software + Service and more....

Calling “CRM” Web services using JScript

Calling “CRM” Web services using JScript

Rate This
  • Comments 20

Since I wrote the post about calling "any" web service from CRM forms (BTW, that is my most viewed post to date!), folks have written to me and asked "what the heck, what about calling “CRM” web services, hello"?

Calling CRM web services from JScript is not the best programming experience that you could imagine, mostly because it is not much fun using strongly typed classes in Jscript code (Atlas solves that problem to a great degree, more on this later) whereas you do get a great developer experience inside Visual Studio with strongly typed classes.

So there are two options to call CRM web services from CRM forms (or from any html/aspx pages using JScript) 1) use a intermediate proxy web service with a simple interface that masks the complexy of strongly typed classes. Such web service can have complex code and calls CRM web services using our WSDL.  This approach may work for many of your scenarios where performance is not as critical as developer experience 2) call CRM web services directly from CRM form using SOAP messages (there is a third option to use Atlas. Michael who is one of our dev leads and I are still thinking about the best way to get that to work, stay tuned).  This approach is less developer friendly to work with since you have to create a SOAP message in JScript, send it to the CRM server and parse the returned XML to get the data that you need, but it should be faster than calling teh intermediate service.  Here is a sample to show you how to do this using JScript and POST.

This sample directly calls CRM web service RetrieveMultiple method and passes a QueryByAttribute object.  The query condition is to retrieve all the accounts that are in the state of Washington (address1_stateorprovince = WA).

First thing I did was to enable tracing and capture the SOAP message for RetrieveMultiple passing in a QueryByAttribute. The tracing file includes both requests and responses. Next, I added the SOAP request string to my POST request on the Jscript code. I post the SOAP message to CRM web service and get the results back in xml. Then I parse the xml to extract the data that I am interested in, in this case a list of account names.  Finally I write the account names on the html page that i am calling the web service from. The sample is written for a standalone html page but you can easily cut and paste the code into Onload, OnSave or OnChange event of any CRM forms.

Make sure you add your server name where it says below.

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">

<title>Access CRM Web Services</title>

<SCRIPT language="JavaScript">

//Call CRM web services directly

function AccessCRMWebServices()

{

var serverUrl = "http://<ADD your Server name here>/mscrmservices/2006";

var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

alert(serverUrl+ "/crmservice.asmx");

xmlhttp.open("POST", serverUrl + "/crmservice.asmx", false);

xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8")

xmlhttp.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2006/WebServices/RetrieveMultiple")

xmlhttp.send("<?xml version='1.0' encoding='utf-8'?>"+"\n\n"+"<soap:Envelope"+

' xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"'+

' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'+

' xmlns:xsd="http://www.w3.org/2001/XMLSchema">'+

' <soap:Body>' +

' <query xmlns:q1="http://schemas.microsoft.com/crm/2006/Query" xsi:type="q1:QueryByAttribute" xmlns="http://schemas.microsoft.com/crm/2006/WebServices">'+

' <q1:EntityName>account</q1:EntityName>'+

' <q1:ColumnSet xsi:type="q1:ColumnSet">'+

' <q1:Attributes>'+

' <q1:Attribute>name</q1:Attribute>'+

' <q1:Attribute>address1_stateorprovince</q1:Attribute>'+

' </q1:Attributes>'+

' </q1:ColumnSet>'+

' <q1:Attributes>'+

' <q1:Attribute>address1_stateorprovince</q1:Attribute>'+

' </q1:Attributes>'+

' <q1:Values>'+

' <q1:Value xsi:type="xsd:string">WA</q1:Value>'+

' </q1:Values>'+

' </query>'+

' </soap:Body>'+

' </soap:Envelope>')

var result = xmlhttp.responseXML.xml;

//Separate the BusinessEntities XML tag

var BEs= result.split("<BusinessEntities>");

//Separate the BusinessEntity XML tag

var BE = BEs[1].split("<BusinessEntity");

//Walk through each Business Entity tag and extract account names

for (i = 0; i < BE.length; i++)

{

first = BE[i].indexOf("<name>")+6;

second = BE[i].indexOf("</name>");

document.writeln(BE[i].substring(first,second) + "<BR>");

}

}

//Simply call the method when the page is loaded

AccessCRMWebServices() ;

</SCRIPT>

</head>

<body>

</body>

</html>

Leave a Comment
  • Please add 8 and 1 and type the answer here:
  • Post
  • PingBack from http://blogs.infinite-x.net/2006/08/29/the-crm-team-rocks-more-sample-code/
  • So, will this work if I am on the laptop client and off line?  Can I still tap into the CRM Web Service or do I need to query my offline data directly?
  • Josh
    This will only work against the CRM server.  There is no offline support in V3.0 (My bad in previous comment).
  • I am trying to do the same thing with the GrantAccess method.  Not having luck with the SOAP part.  Any advice on how I can find out how to do this?

    I am not sure how to include the PrincipalAccess information (i.e. AccessMask, prinicpal) and Target into the SOAP envelop.

    Any suggestions?
  • We've copied this code (from the line that reads "var server url=..." to the closing bracket for the for loop) for testing purposes into an OnLoad event into a entity. We modifed the address1_stateorprovince field of an account to "WA" so it would return that account, but it does not. The responseXML is empty, so then the code obviously fails when trying to access a null array element (BEs[1]).

    Any idea what might be causing this?
  • Hi Darin
    If you make a GrantAccess (or any other request) call while tracing is on, you can see the SOAP message in the trace file.  For GrantAccess, you will see this SOAP message:

    SOAP Request:
    URL:CrmService.asmx
    HttpHeader:SOAPAction: http://schemas.microsoft.com/crm/2006/WebServices/Execute

    SOAP Xml:
    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
    <Request xsi:type="GrantAccessRequest" xmlns="http://schemas.microsoft.com/crm/2006/WebServices">
    <Target xsi:type="TargetOwnedAccount">
    <EntityId>948c2aa0-984c-4439-a92a-c015b32dcba9</EntityId>
    </Target>
    <PrincipalAccess>
    <Principal xmlns="http://schemas.microsoft.com/crm/2006/CoreTypes">
    <PrincipalId>6ce4df0c-0948-da11-a7a7-00065ba4662d</PrincipalId>
    <Type>User</Type>
    </Principal>
    <AccessMask xmlns="http://schemas.microsoft.com/crm/2006/CoreTypes">WriteAccess</AccessMask>
    </PrincipalAccess>
    </Request>
    </soap:Body>
    </soap:Envelope>

    Now all you need to do is to create a string with this soap message like what i did with QueryByAttribute and send it to the server.

    Good luck
  • Hi Kyle
    There might be a number of possible reasons and debugging tips 1) Make sure that you have included your server name where it says so in the code 2) Make sure activeX is enabled in your browser(go to IE -> Settings -> check the box with prompt for Activex) 3) if you are sure the browser is calling the server, make sure if the server is receiving the web service call by turning on the tracing and viewing the log to ensure the SOAP call is recieved.
  • Thanks for this awesome code.  I was able to modify it to create a picklist of contact names for the related account on an opportunity form and thus able to have multiple contacts, ie-client contact, client executive contact, etc on the opportunity form and views.

    I was also able to use this method to have multiple users on a form as well (main owner, technical contact, project leader, etc)

    My question is this, where do you find the XML schema structure to structure the query request in XML format?  

    I understand the "querybyattribute" structure, but what if I want to do something similar using "querybyexpression"?  I can do this in a ASPX page using C# but this would run faster if I could do this in an onchange like above.  I can't seem to locate this in the SDK, or am I missing something *really* obvious?  I am just unclear of where to put/embed things like <linkedentity> and <filterexpression>, etc

    Thanks,

    Nick

  • Nick

    Great to hear you are using this.  Two ways to find out about the schema and build your XML 1) use the CrmService.asmx web service WSDL,  the WSDL includes the schema for QueryExpression and all of the rest of CRM types 2) Enable tracing (follow the link in the my post), make a web service call using C# and view the tracing log.  The tracing log will have the SOAP XML that you need to use in your form JScript.

  • We've tried this code in the CRM Web Browser client and it works fine. The Outlook client, however, fails when it reaches the "xmlhttp.open()" line. The error we receive is an "Unknown name" error.

    Any ideas what may be causing this?

    Thanks,

    - Kyle

  • Webservices Webservices Webservices....alla pratar om dem, alla vill ha det och vi har det :) Visste

  • Or you can use Microsofts own JavaScript classes (or modified versions of them) like I did here: http://www.sharepointdemo.biz/blogs/bjarne/default.aspx?BlogId=101

  • Nick,

        Another way, one that seemed easier than the trace log, was to use a tool called WebserviceStudio.  Just point to your webservice (ie. CrmService.asmx) and press a button to get all the available method in the web service.

    Then you can choose between a QueryExpression or QueryByAttribute, etc.  Then just fill in your criteria and press another button.  On the Request/Response tab will be your SOAP messages, just how you need them.

    Took me an hour to figure out how to use it correctly to generate the correct SOAP messgae (if you set it up wrong, you get an error).

    Hope this app helps you, too.

    Darin

  • The first time the web-service is called after opening CRM, I'm being prompted with a Login.  Is there any way to eliminate this?

    Thanks

    Ken

  • We've been using this code for quite some time and it works great. However, if we're using the Outlook Laptop Client, and we're trying to access "http://localhost:2525/MSCRMServices/2006" (the local website), the process fails.

    Is there a way to get this to work?

    Thanks,

    - Kyle

Page 1 of 2 (20 items) 12