I recently worked with a client, implementing Dynamics CRM, that had a very rigid order entry process.  Due to this fact, they had developed an in-house order entry application using Silverlight.  After much deliberation, it was decided that it would be easier to re-plumb the existing LOB application and leverage the business rules built into the form as opposed to re-creating the complex business logic in the Dynamics CRM 2011 order form using JavaScript.  The client wanted to leverage the search and list functionalities of Dynamics CRM while still using the existing custom order entry form; therefor an external link was not an option.  So the task at hand was to replace the order form with the Silverlight application.

Method 1

The most obvious (and supported) method to do this was to add JavaScript to the CRM order form’s order_onload event.  We accomplished this by inserting the following to the form’s event:

function order_onload() {
    if (crmForm.FormType == 2 || crmForm.FormType == 1) {
        window.top.location.href = tOrderUrl + “?oid=” + crmForm.ObjectId;
    }
}
This method achieved our desired results but not without a few drawbacks.  Number one of which was that a user could break the load sequence by escaping the load of the page prior to the JavaScript running and thus breaking our enforcement of the custom form.  After more investigation and testing, we decided that we needed to go another route.

Method 2 (NOTE: This modification is completely UNSUPPORTED )

Investigating the Dynamics CRM we found that the method responsible for opening an entity form could be traced to a function entitled “openObject” in the Global.js file located here:  “\Microsoft Dynamics CRM\CRMWeb\_static\_common\scripts\”.  The original method looked like this:

function openObject(type, id, parameters, urlPrefix, mode, extraParams) {
    if (typeof type === “string”) type = parseInt(type, 10);
    var $v_0 = “”;
    if (id) {
        if (type === 1039) {
            var $v_1 = new RemoteCommand(“SystemCustomization”,”CheckSavedQuery”, null);
            $v_1.SetParameter(“savedQueryId”, id);
            if (!$v_1.Execute(null).Success) return null
        }
        $v_0 += “?id=” + CrmEncodeDecode.CrmUrlEncode(id)
    }
    if (!IsNull(parameters)) {
        $v_0 += !$v_0.length ? “?” : “&”;
        if (parameters.length > 0 && (parameters.charAt(0) === “?” || parameters.charAt(0) === “&”)) parameters = parameters.substr(1);
        $v_0 += parameters
    }
    return openFrmObject($v_0, buildWinName(id), type, urlPrefix, mode, extraParams);
}

There’s obviously much more to the opening of the window.  As evidenced by the function above, this is only the entry point in the process of opening a CRM form (with openFrmObject as the next function called) but it seemed a logical place to interrupt the process and insert our form.  As we already knew the type code of a sales order (1088), inserting our logic was fairly easy:
function openObject(type, id, parameters, urlPrefix, mode, extraParams) {
    if (typeof type === “string”) type = parseInt(type, 10);
    var $v_0 = “”;
    if (id) {
        if (type === 1039) {
            var $v_1 = new RemoteCommand(“SystemCustomization”, “CheckSavedQuery”, null);
            $v_1.SetParameter(“savedQueryId”, id);
            if (!$v_1.Execute(null).Success) return null
        }
        $v_0 += “?id=” + CrmEncodeDecode.CrmUrlEncode(id)
    }
    if (!IsNull(parameters)) {
        $v_0 += !$v_0.length ? “?” : “&”;
        if (parameters.length > 0 && (parameters.charAt(0) === “?” || parameters.charAt(0) === “&”)) parameters = parameters.substr(1);
        $v_0 += parameters
    }
    //added to open custom Silverlight window when destination object is a sales order
    //10/15/2011 – Corey Brown
    //—————————-Replaced———————————————
    //return openFrmObject($v_0, buildWinName(id), type, urlPrefix, mode, extraParams);
    //——————————with———————————————–
    if (type == 1088) {
        window.open(“http://crmUrl:8000/O2C.Web/O2CTestPage.aspx?oid=” + CrmEncodeDecode.CrmUrlEncode(id), buildWinName(id), “menubar=no,toolbar=no”);
    }
    else {
        return openFrmObject($v_0, buildWinName(id), type, urlPrefix, mode, extraParams);
    }
    //—————————end mods———————————————
}
This was a quick and dirty way to accomplish our goals.  Taking it a step further would be to make the url dynamic (as in our form_onload event) and to potentially handle the different form types (new vs. update) differently.  In conclusion, modifying the internal Dynamics CRM script files is usually not a wise route but some things can be accomplished if you’re willing to take the risk.  Some things to consider before making this type of modification:

1. As noted previously, this method is COMPLETELY UNSUPPORTED by Microsoft and if you mess things up you won’t get any help so make sure you back any modified files up (obviously) and test, test and test again.
2. These files are sometimes updated during the application of rollups so be aware that any modifications made may need to be added again and potentially redesigned after applying a rollup.
3. This is an primarily an “on premise” solution.  Modifying the js files in Dynamics CRM Online is not an option.