Sunday, January 13, 2013

Script# (ScriptSharp) and CRM: The good and the bad

If you are familiar with Script# you probably understand how it can accelerate JavaScript development and completely eliminate annoyances such as accidental JavaScript syntax errors. However, does it work well for Dynamics CRM for scripts and web resources?

If you are not familiar with Script#, here is a very simple definition: Write your code in C# and you can then compile it into a JavaScript (instead of programming in JS directly). I have been using Script# for many years now (and love it), but I recently took the challenge for the first time to use it for designing and deploying all script customizations for an enterprise CRM project and quickly realized that there are a few issues about Script# and CRM that will make me think twice next time. Let’s start with the “good”:



1. Forget about JS syntax. Honestly, I hate JavaScript and client programming. One of the reasons is because I find it too error prone, I don’t know how many times I have run into issues with my JavaScript and often turns out to be something like forgetting a curly braket “}” somewhere in the syntax or accidentally typing a capital letter when it shouldn’t be. I am devoted to C# and that’s why I’m so motivated with Script#; isn’t it just awesome that I can write all my JavaScripts in C#, a language that I know inside out, gives me compile-time errors and intelli-sense? I’m sold already! Also because you write your form scripts in C#, you could even share some code between plugins (server) and web resources (client-side JS)!



2. Excellent Script# Xrm.Page Library. You can download for free this library that Gayan Perera has shared with the community. It is as simple as adding a reference assembly to your Script# project and now you have access to the entire Xrm.Page object model from Script# including intellisense for different APIs and enumerations available in the CRM SDK. This is an amazing productivity gainer.



3. Access to mscorlib from your JavaScripts. JavaScripts can get ugly with complex operations. Having a subset of mscorlib available from Script# makes things much simpler. You can have access to useful classes like String, Dictionary, Queue, List<T>, CultureInfo, XmlDocument, XmlHttpRequest , Math and many more, and all this with the intelli-sense we love. Some of these functions would be painful and/or ugly to implement in JavaScript alone. You can also use OOP/C# concepts such as inheritance, static classes and members, Properties, Events and Delegates. This way you can program your JavaScripts in C#and you can use API’s and syntax you are familiar with from .Net. Although it would be possible to do al this in JavaScript, for a C# developer, the usability and efficiency to write Script# does not compare with that of writing JavaScript.



On the other hand, I ran into the following “issues”:

1. Library size. When you make use of any API from a referenced assembly (except Xrm.Page) then you need to include the JavaScript version of that referenced assembly (e.g. mscorlib.js) to be loaded with the CRM form. These libraries can be big and typically, you only need a small subset of the library. It could slow down loading the forms, however, you will have the same problem even without Script# when for example you want to use the JQuery library.

2. You cannot reference any JavaScript code from Script#. If you want to re-use a JavaScript library from a previous project or a library you found online, you cannot reference any JS function from a Script# project. You would have to write “empty wrappers” in C# for each JavaScript function you plan to use, then compile it as a Script# library and then add the reference assembly to your code. It is not too complicated but it adds some pain.

3. AJAX incompatibility. I noticed that my dates in the form were not getting formatted as per the CRM user settings and some other fields and controls had strange issues (e.g. missing the month from the calendar control). After some investigation the culprit ended up being Script#. The reason: mscorlib.js defines classes and functions such as Date.prototype.format and Date.prototype.localeFormat. These functions are also defined in the AJAX framework that the CRM application uses in global.ashx and guess what: They are not implemented the same way. Because the CRM application relies on the MicrosoftAjax.js implementation it will be buggy if it uses the mscorlib.js implementation. Unfortunately, as soon as you add mscorlib.js library to your form, it will overwrite the functions from global.ashx and there is no way to “force” the CRM application to use the functions defined in global.ashx instead. I had to implement an emergency workaround to fix this problem which consisted in adding another JS library to the form, which would define the functions back with the AJAX implementation (something like overwriting the overwrite). Ugly, but it fixed the problem.



In summary, I had a good experience using Script# for CRM, but the issue with AJAX framework became a deal-breaker for me. Other things that I will explore in the future are TypeScript and the new Xrm.Page script template available with the CRM SDK 5.0.13+ which gives you intellisense for your CRM JavaScripts. TypeScript sounds promising since it is simply a superset of JavaScript which allows you to reference other JavaScript libraries; however, it is not C#-based and the syntax is not the same, so it would be yet another language to learn.

4 comments:

  1. Nice article, but thought I’d let you know few things that you can use to get around the mscorlib.js issue, you only need to include mscorlib.js if you’re using any of the script# mapped functions which are part of System.dll (script# reference, eg: string.Format()).

    If you use jQuery and stick to the standard stuff you don’t need mscorlib.

    Cheers
    Gayan

    ReplyDelete
  2. Thanks for your feedback Gayan! But how do you use jQuery functions from Script# if you cannot reference a JS library?

    ReplyDelete
  3. Script# has a wrapper for jquery. If you download the latest version from Github, create a new Script# jQuery Library project you'll see that it adds a reference called jQueryApi which wraps all jquery calls.

    ReplyDelete
  4. There are hand-coded C# mappings to the jQuery 1.6.1 API created as part of the Script# project.

    https://github.com/nikhilk/scriptsharp/tree/cc/src/Libraries/jQuery/jQuery.Core

    ReplyDelete