Script# (C# to Javascript) Meets Dynamics CRM 2011

Paul Nieuwelaar, 05 April 2012

If you haven’t already heard of Script#, it is basically C# that compiles into Javascript. You still use the Javascript language, such as document.getElementById, although it’s written using C# standards and regulations. You can write pages of C# code to perform your javascript needs, and then when you build the solution through Visual Studio, a nicely compiled Javascript file will be created. This can then be uploaded or referenced by your web pages.

 Script# (C# to Javascript) Meets Dynamics CRM 2011

Script# (C# to Javascript) Meets Dynamics CRM 2011

The best part of Script# is that it uses intellisense, so you can just start typing, and it will give you all the supported options. If there are any errors (such as using a variable that doesn’t exist) it will be identified immediately.

 Script# (C# to Javascript) Meets Dynamics CRM 2011

In Dynamics CRM 2011, we use Javascript all the time. Usually this is messy, freehand code that has been typed straight into the webresource. Even when edited through Visual Studio, errors are often never identified for you. Also, unless you write a lot of Javascript in CRM 2011, it can sometimes be difficult to remember the exact terminology.

So the obvious question is: How do we use Dynamics CRM 2011 Javascript (Xrm.Page) with Script#?
The answer is simple, after installing Script# for VS 2010, we can create a new Visual Studio 2010 Script# Script Library Project. Within this project, we can add a reference to the Xrm.Page Library downloaded from CodePlex. You can also find Documentation on how to install and get started with the Xrm.Page Library.

Script# (C# to Javascript) Meets Dynamics CRM 2011 

Once configured, we can start creating our Methods using the Javascript terminology such as Page.GetAttribute(“fieldname”). You can use any supported functions currently documented under MSDN Xrm.Page. This means you can write all your Javascript in a tidy Visual Studio project, using separate Namespaces and Folders if required. The best part is you don’t have to think as much when writing the code, as all the CRM Javascript functions are recognized, and can all be easily used.

I have taken a Javascript example from a recent CRM project to see how it would work in Script#. The example I used needs to check on save of a record to make sure that two client (contact) records are not the same, and prevent the user from saving if they are. Here is how the code is written using Script#:

           //on save of an agreement, make sure client 1 and 2 are not the same contact
        public void CheckClientsDoNotMatch(ExecutionContext executionObj)
        {
            Lookup[] client1Value = Page.GetAttribute("new_client1id").GetValue<Lookup[]>();
            Lookup[] client2Value = Page.GetAttribute("new_client2id").GetValue<Lookup[]>();

                 //before comparing the id's, make sure both lookups are set
            if (client1Value != null && client2Value != null)
            {
                //if client2 is set by silverlight, its uppercase, and has no { } so need to make them the same!!
                string client1Id = client1Value[0].Id.ToLowerCase();
                string client2Id = client2Value[0].Id.ToLowerCase();

                client1Id = client1Id.Replace("{", "");
                client1Id = client1Id.Replace("}", "");
                client2Id = client1Id.Replace("{", "");
                client2Id = client1Id.Replace("}", ""); 

                if (client1Id == client2Id)
                {
                    Script.Alert("Client 2 must not have the same 'Client Record' as Client 1. Please go back and update the Client Records.");
                    Page.GetControl("new_client2id").SetFocus(); //set focus to the client 2 lookup field
                    executionObj.GetEventArgs().PreventDefault(); //prevent them from saving
                }
            }
        } 

After writing our code, we can build the project; this compiles our code into a single compacted javascript file, located in your specified location (or the bin folder by default). This file will be called <<project name>>.js, and can be uploaded directly into CRM as a webresource. You will notice this Javascript file has had all the casing and terminology set in the Script# Library converted into the CRM supported methods. Here is what the resulting Javascript looks like:

Frosty.Global.prototype = {   

    checkClientsDoNotMatch: function Frosty_Global$checkClientsDoNotMatch(executionObj) {
        /// <param name="executionObj" type="Xrm.ExecutionContext">
        /// </param>
        var client1Value = Xrm.Page.getAttribute('new_client1id').getValue();
        var client2Value = Xrm.Page.getAttribute('new_client2id').getValue();
        if (client1Value != null && client2Value != null) {
            var client1Id = client1Value[0].id.toLowerCase();
            var client2Id = client2Value[0].id.toLowerCase();
            client1Id = client1Id.replace('{', '');
            client1Id = client1Id.replace('}', '');
            client2Id = client1Id.replace('{', '');
            client2Id = client1Id.replace('}', '');
            if (client1Id === client2Id) {
                alert("Client 2 must not have the same 'Client Record' as Client 1. Please go back and update the Client Records.");
                Xrm.Page.getControl('new_client2id').setFocus();
                executionObj.getEventArgs().preventDefault();
            }
        }
    }
} 

We can now call the functions in this file from our Entity Forms just like normal, and the Javascript will behave as it should when previewing our results. But don’t just take my word for it, download Script# and the Xrm.Page Library now so you can try it out for yourself!