A Microsoft Dynamics CRM JavaScript SDK in Celebration of an Amazing Year! 

It was just about a year ago that Ascentium and Invoke Systems came together and what a year it's been.  Here are some of the highlights:

  • Over 15,000 additional seats of Microsoft Dynamics CRM sold.  This was just for FY08!
  • Two Pinnacle awards at Convergence, one for the Healthcare Industry and then the award for Overall Excellence for our work with the United States Air Force.
  • CRM Partner of the Year finalist.  No the CRM Practice didn't win, but Ascentium did win Partner of the Year for Portals and Collaboration.  Being a finalist in one and then winning the other is a pretty big deal since we all know that CRM + MOSS = The Future of Software Development!
  • We added another MVP to our ranks.  Within a month of each other, Ross (you've seen his blog posts) made partner here at Ascentium and then Microsoft Dynamics CRM MVP.  Both pretty impressive achievements.

While reflecting on how great this year has been, we were thinking of how we could celebrate it.  So, instead of a big party, we're going to go one better and put out to the community a tool we've been using this last year that has made our lives so much easier!

Below is some basic documentation and samples and the rest you should be able to figure out pretty quickly.  This is not officially supported and it doesn't wrap the platform in its entirety, but it's got in it the functionality we all use the most.  So enjoy and let us know what you think and if this was beneficial or not.  We'll probably be adding additional functionality in the future and depending on the word of mouth this gets we'll see how much further we take this.

Ascentium CrmService Samples

The CrmService.js script supports sending messages directly to the CRM 4.0 web service utilizing only JavaScript. You can use this file in your own ASPX pages, from with CRM forms or virtually anywhere.

The following methods are supported:

  • Create
  • Retrieve
  • Update
  • Delete
  • Fetch
  • Associate
  • Disassociate
  • SetState

For many of the of these you can also pass in a callback function so they can execute asynchronously.

Create, Retrieve, Update, Delete Sample

This sample shows how to Create, Retrieve, Update and Delete records within CRM. Notice when creating the Contact that to set the parentcustomerid there is a special CrmLookup object you need to use. Use this for all lookups.

function Run()
{
    //create the Ascentium_CrmService object
    var oService = new Ascentium_CrmService("MicrosoftCrm", "http://localhost:5555");

    //create an entity
    var beAccount = new BusinessEntity("account");
    beAccount.attributes["name"] = "Ascentium";
    beAccount.attributes["numberofemployees"] = 600.00;
    var sAccountId = oService.Create(beAccount);

    alert("Account Created. Account ID = " + sAccountId);

    //update an entity
    var beAccountToUpdate = new BusinessEntity("account");
    beAccountToUpdate.attributes["accountid"] = sAccountId;
    beAccountToUpdate.attributes["revenue"] = 1000000000.00;
    oService.Update(beAccountToUpdate);

    alert("Account Updated");

    //retrieve an entity
    var asCols = ["name", "revenue", "createdon", "createdby"];
    var beRetrievedAccount = oService.Retrieve("account", sAccountId, asCols);

    alert("Account Retrieved: " +
    beRetrievedAccount.attributes["name"].value + " : " +
    beRetrievedAccount.attributes["revenue"].value + " : " +
    beRetrievedAccount.attributes["createdon"].value + " : " +
    beRetrievedAccount.attributes["createdby"].value);

    //create an entity with a lookup attribute
    var beContact = new BusinessEntity("contact");
    beContact.attributes["firstname"] = "Joe";
    beContact.attributes["birthdate"] = "2008-01-01T00:00:00";
    beContact.attributes["parentcustomerid"] = new CrmLookup("account", sAccountId);
    var sContactId = oService.Create(beContact);

    alert("Contact Created: " + sContactId);

    //delete an entity
    oService.Delete("account",sAccountId);

    alert("Account Deleted");
}

Fetch Sample

This sample shows how to use the Fetch query language to pull back collections of entities based on the passed in query. For more information on the Fetch query language search for "Using FetchXML" in the CRM 4.0 SDK on MSDN.

function Fetch()
{
    //create the Ascentium_CrmService object
    var oService = new Ascentium_CrmService(orgName.value, serverUrl.value);

    //execute a Fetch query
    var sFetchXml = "<fetch mapping='logical'><entity name='account'><attribute name='accountid'/><attribute name='name'/></entity></fetch>";
    var aoFetchResult = oService.Fetch(sFetchXml);

    //iterate through the aoFetchResult collection
    var sResults = "Accounts:\n";

    for (var i = 0; i < aoFetchResult.length; i++)
    {
        var beResult = aoFetchResult[i];
        sResults += i + ": " + beResult.attributes["accountid"].value + ", " + beResult.attributes["name"].value + "\n";  
    }

    alert(sResults);
}

Asynchronous Sample

This sample shows how to use callbacks to allow the functions to perform asynchronously.

function WhoAmI()
{
    //create the Ascentium_CrmService object
    var oService = new Ascentium_CrmService(orgName.value, serverUrl.value);

    //define a fetchxml query that returns only the current user
    var sFetchXml = "<fetch mapping=\"logical\"><entity name=\"systemuser\"><attribute name=\"fullname\"/><attribute name=\"systemuserid\"/><filter type=\"and\"><condition attribute=\"systemuserid\" operator=\"eq-userid\"/></filter></entity></fetch>";

    //execute the fetch asynchronously by passing a callback function to the Fetch method
    oService.Fetch(sFetchXml, WhoAmICallback);
}

function WhoAmICallback(aoFetchResult)
{
    if (aoFetchResult.length > 0)
    {
        var beUser = aoFetchResult[0];

        alert("You are " + beUser.attributes["fullname"].value + ", System User ID = " + beUser.attributes["systemuserid"].value);
    }
}

Associate/Disassociate Sample

This sample shows how to Associate and Disassociate records. This is used when you have a many-to-many relationship. The fifth parameter is the actual name of the N:N relationship.

function Associate()
{
    //create the Ascentium_CrmService object
    var oService = new Ascentium_CrmService(orgName.value, serverUrl.value);

    //create an account
    var beAccount = new BusinessEntity("account");
    beAccount.attributes["name"] = "Ascentium";
    var sAccountId = oService.Create(beAccount);

    alert("Account Created");

    //create a lead
    var beLead = new BusinessEntity("lead");
    beLead.attributes["fullname"] = "Mr. Lead";
    var sLeadId = oService.Create(beLead);

    alert("Lead Created");

    //associate the account and the lead
    oService.Associate("account", sAccountId, "lead", sLeadId, "accountleads_association");

    alert("Account and Lead Associated");

    //disassociate them
    oService.Disassociate("account", sAccountId, "lead", sLeadId, "accountleads_association");

    alert("Account and Lead Disassociated");

    //delete the account
    oService.Delete("account", sAccountId);

    alert("Account Deleted");

    //delete the lead
    oService.Delete("lead", sLeadId);

    alert("Lead Deleted");
}

SetState Sample

This sample shows how to set the State of a record.

function SetState()
{
    //create the Ascentium_CrmService object
    var oService = new Ascentium_CrmService(orgName.value, serverUrl.value);

    //create an account
    var beAccount = new BusinessEntity("account");
    beAccount.attributes["name"] = "Ascentium";
    var sAccountId = oService.Create(beAccount);

    alert("Account Created");

    //deactivate the account
    oService.SetState("account", sAccountId, "Inactive", -1);

    alert("Account State set to Inactive");

    //delete the account
    oService.Delete("account", sAccountId);

    alert("Account Deleted");
}

So there you go!  Just a couple of samples to get you started.  All you need to do is download the CrmService.js and the accompanying sample page.  The organization name we're using for these sample are the same ones you will find in the Microsoft Dynamics CRM 4.0 Virtual Machine.  We usually create a sub-directory in the "CRMWeb\ISV" directory called "Ascentium" and drop these sorts of files in there but you can put them wherever you want as long as you point the script tag in the HTML file to where you actually put the CrmService.js file.

Download AscentiumCrmService.zip

Last but not least, I want to recognize Erik Pool, the developer on the National CRM Practice here at Ascentium who saw the need for this functionality and built it in the first place.  Thanks also to Aaron Elder for getting the code ready to ship out to the community.  As I said earlier, we hope you all find this as useful as we have, we look forward to hearing from you on how much it has (or hasn't) helped.  Look for future posts on how to effectively use this in more real world scenarios.

Comments
Wow! This is one of the most useful Crm related script I have seen!

Thank you so much for this wonderful contribution, It will help me greatly in future projects!
Hello, This post is fantastic, i'm starting with dynamics, and i was having some dificulties in developing some features required in the system and this realy helped me.

one of the things I most appreciated was the organisation of the code, I do not know if it was to be cleaner, but really was a great help to understand how the mechanism works and how things are supposed to be!

thanks a lot!

p.s.: should this also work in ofline mode!?
Yes, this should work offline against the offline local API. Remember the offline web services are only active when the client is actually in offline mode.
Wonderful Job...! Keep it up. This would greatly help MSCRM Community.
---------------------------
Microsoft Internet Explorer
---------------------------
Ascentium_CrmService Error:

soap:ServerServer was unable to process request. 0x80040265 The given key was not present in the dictionary. Platform

XML:
<?xml version="1.0"?>

<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><soap:Fault><faultcode>soap:Server</faultcode><faultstring>Server was unable to process request.</faultstring><detail><error>

<code>0x80040265</code>

<description>The given key was not present in the dictionary.</description>

<type>Platform</type>

</error></detail></soap:Fault></soap:Body></soap:Envelope>



HTTP: 500 - Internal Server Error

I got this error while creating an Account, This problem occured in callback method. _CreateCallback. I am Creating an Account only by Adding "name" attribute. I have commented numberofemployees attribute too.

//create an entity
var beAccount = new BusinessEntity("account");
beAccount.attributes["name"] = "Ascentium";
//beAccount.attributes["numberofemployees"] = 600.00;
var sAccountId = oService.Create(beAccount);

Please help me out to run this script.

Thanks in advance,
Ravishankar
I have to agree with Eran in that this is one of the most useful scripts I've found. Great job and thank you!
Superb stuff, a big timesaver.
THANKS!
Spectacular work. I love it so much I had to name names on my blog.

Nice one.
This looks like great stuff but I am having difficulty making it run. I unzipped and placed the files in /ISV/ascentium. When I run the html page and click on any of the functions I get an 'Invalid Character' javascript error pointing to line 2. This is line 2: <html xmlns="http://www.w3.org/1999/xhtml" >

I am also wondering if this can be used within the onload event of an MS CRM form. Any example are much appreciated. Thanks
Exceptional!

I am recently involved with an important CRM solution and have been deciphering ways to deal with CRM Entities from Javascript, to as much extent as possible, in an object oriented approach and not from raw xml and munge parsing of data.

Your wonderful code just saved me quite a bit of headache and will allow moving forward faster, focusing on the goals and not the minutia of OO wrap mechanics to 'fake' OO from js in the way I want.

Thanks!
-MLL
This looks awesome! I can run the CrmServiceExamples.htm fine from within the ..crmweb\isv\ascentium folder.
I must be missing a step somewhere to get this to run from within a crm form using the onload event.
I get an "Ascentium_CrmService is undefined" error.

Can anyone please clue me in on howto get access to the CrmService.js functions from within a crm form? I'm using crm 4.0.

Thanks! - Jim
When in the context of the CRM form, you will need to "load" our script during the Form's onload event. Here is an example:

var oScript = document.createElement("&lt;script src='/isv/crmservice.js' language='JavaScript' &gt;");
document.getElementsByTagName("head")[0].insertAdjacentElement("beforeEnd", oScript);

Note, this script will LOAD asynchronously so you will need to have a timer or something to wait for it to full parse and load.
Hi,

Thx for the "code"! This is a greate piece of code!

There just one problem with it :
1. You need to put it on a global "server" where you can load your "Script"!
2. Needs an installation on every desktop if you want it to make it work "offline"!

The solution would be to copy "all" the code and put it in the onload of your "Page" where you need it!

But it sure is really Handy!!! Because if I needed to create a record with "Javascript", I ran a little tool "C# to Javascript converter" and then I had my "SOAP" message I could execute.

Thx again for the "Magnificant"-code, is a solution for people who doesn't want to run "Plug-in's" or hate programming in Visual Studio!

Be sure to load your "External" js-file correctly :

var script = document.createElement('script');
script.language = 'javascript';
script.src = '/Custom/JavaScript/opportunityOnloadOnsave.js';
script.onreadystatechange = OnScriptReadyState;
document.getElementsByTagName('head')[0].appendChild(script);

function OnScriptReadyState()
{
if (event.srcElement.readyState == "complete")
{
//perform onload scripts
CustomOnLoad(); // some function from your custom js file
}
}

Have fun,
Frederic
Just being stupid I think. I have this code in my CRMform_load

var oScript = document.createElement("&lt;script src='/isv/crmservice.js' language='JavaScript' &gt;");
document.getElementsByTagName("head")[0].insertAdjacentElement("beforeEnd", oScript);

and in the change event of a field I invoke it. The Ascentium_CrmService isn't found.

What am I missing??
Remember that the script file will load asynchrnously, so you need to wait for it to download and parse.
Add a New Comment
Name

Email Address

Url

Comment