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.
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.
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
Add a New Comment
Name

Email Address

Url

Comment