Tuesday 25 September 2012

Dynamics CRM 2011 Reduce your javascript code footprint with Microsoft Ajax Minifier tool

Did you know about Microsoft Ajax Minifier tool? I use this tool for some time now and I think is great, it gives developers the chance to reduce their 'code footprint' by compressing javascript and css files.

You can download the tool here:
http://ajaxmin.codeplex.com/

As customization in CRM 2011 are more flexible, developers have more functionality on their side to impress customers, it's easy to end up with long and complex javascript files which end up increasing the download and processing time; so a good practice in a production environment is to remove all comments and un-necessary spaces to compress the code, with Microsoft Ajax minifier tool, can do this for us and also minify the code compressing it to the optimal size.

The same concept as jquery-minimized version, I would recommend in a production environment minimize all your code to get optimal performance.

Below is an example of a normal javascript code from a previous post on a jquery duplicate detection pop-up.


function idp() {
var isCreateForm = Xrm.Page.ui.getFormType() == 1;
if (isCreateForm) {

$.ajaxSetup({cache:false});
$(document.body).append("
A possible duplicate record was found, please review:
");

$('#name').focusout(function() {

var name = Xrm.Page.getAttribute('name').getValue();
var query = "/AccountSet?$filter=Name eq '"+name+"'";

var serverUrl = Xrm.Page.context.getServerUrl();

    if (serverUrl.match(/\/$/)) {
        serverUrl = serverUrl.substring(0, serverUrl.length - 1);
    }

    var ODataURL = serverUrl + "/XRMServices/2011/OrganizationData.svc" + query;

    $.ajax({
        type: "GET",
        contentType: "application/json; charset=utf-8",
        datatype: "json",
        url: ODataURL,
        beforeSend: function (XMLHttpRequest) {
            XMLHttpRequest.setRequestHeader("Accept", "application/json");
        },
        success: function (data, textStatus, XmlHttpRequest) {
           var entities = data.d.results;
    $.fx.speeds._default = 1000;
    $(document).ready(function() {
        $("#dialog").dialog({
            autoOpen: false,
            show: "blind",
            hide: "explode",
            modal: true
        });

    });
if(entities.length > 0 ) {
  for( i=0; i< entities.length; i++)
  {
     var entity = entities[i];
}    

var entityUrl = "main.aspx?etn=account&pagetype=entityrecord&id=";
$(document).ready(function() {
                             $("#link").empty();
                             $("#link").append(document.createTextNode(entity.Name));
                             $("a#link").attr("href","/"+entityUrl+"%7B"+entity.AccountId+"%7D"+"");
                             $('#dialog').dialog("open");
});          
}

        },
        error: function (XmlHttpRequest, textStatus, errorObject) {
            alert("OData Execution Error Occurred");
        }
    });
});
}
} 
 

Install Ajax minifier tool and from the command prompt run:
AjaxMin.exe idp_engine.js -out idp_engine_min.js

The end result will be something like this:

function idp(){var n=Xrm.Page.ui.getFormType()==1;if(n){$.ajaxSetup({cache:!1}),$(document.body).append(""),A,possible,duplicate,record,was,found,please;n:");";$("#name").focusout(function(){var r=Xrm.Page.getAttribute("name").getValue(),u="/AccountSet?$filter=Name eq '"+r+"'",n=Xrm.Page.context.getServerUrl(),t;n.match(/\/$/)&&(n=n.substring(0,n.length-1)),t=n+"/XRMServices/2011/OrganizationData.svc"+u,$.ajax({type:"GET",contentType:"application/json; charset=utf-8",datatype:"json",url:t,beforeSend:function(n){n.setRequestHeader("Accept","application/json")},success:function(n){var u=n.d.results,f,e;if($.fx.speeds._default=1e3,$(document).ready(function(){$("#dialog").dialog({autoOpen:!1,show:"blind",hide:"explode",modal:!0})}),u.length>0){for(i=0;i

We have compressed the code from:
Original Size: 1953 bytes; reduced size: 1085 bytes (44.4% minification)

The tool also provides an approximate Gzip compression:

Gzip of output approximately 887 bytes (18.2% compression)

Summary
This tool can help reduce the code footprint on customizations with large usage of javascript and css files, and is a great way to tackle latency and keep the code running at optimal performance.

Hope this was useful.

Saturday 15 September 2012

Dynamics CRM 2011 Provision Rollups per Organization

With Dynamics CRM 2011 we can now deploy update rollups without updating the Organization database, the advantages are:
  1. Deploy Update Rollups per Organization and not to the entire Environment.
  2. Test binaries before updating the database
By default it updates the database as you install an update rollup, to stop it from automatically update the databases, run the following powershell script:

Open PowerShell copy+paste the below commands; on the last line hit enter:

Add-PSSnapin Microsoft.Crm.PowerShell
$setting = New-Object "Microsoft.Xrm.Sdk.Deployment.ConfigurationEntity"
$setting.LogicalName = "Deployment"
$setting.Attributes = New-Object "Microsoft.Xrm.Sdk.Deployment.AttributeCollection"
$attribute = New-Object "System.Collections.Generic.KeyValuePair[String, Object]" ("AutomaticallyInstallDatabaseUpdates", 0)
$setting.Attributes.Add($attribute)
Set-CrmAdvancedSetting -Entity $setting

Note: what the powershell script does, sets to 0 the database field AutomaticallyInstallDatabaseUpdates on the DeploymentProperties table of the MSCRM_CONFIG database.

Now if you Install the latest rollup; when you open deployment manager the column 'version' should still show the previous RU version for all organizations; to update the database for a specific organization right click the organization you want to update and click Update:













 If you get the below error, stop the Asynchronous service and try again.



















 
 



















After you update the organization, you now have one organization with RU6 and other with RU10:







You ready for testing :)

Hope was helpful.

Tuesday 4 September 2012

Dynamics CRM 2011 leverage duplicate detection with jquery

Have you come across a situation where users take a considerable amount of time filling in a form and at the end the CRM duplicate detection pops-up?

With Jquery we can pro-actively check for duplicate records performing a number of checks on the background; on a successful trigger alert the user.


The process is straight forward, however I have used jquery CSS UI libraries to give the solution a better look-and-feel. You can download the CRM unmanaged solution on the following link:
http://gallery.technet.microsoft.com/Dynamics-CRM-2011-3e9fdb10

If you would like to change the pop-up colour and layout, look at the available jquery UI libraries:
http://jqueryui.com/

When you download the solution and import it into CRM, load the following resources on the account form properties:


Below is the javascript code that performs the duplicate check.  On this example it checks for the account name, however you can extend this and perform multiple checks and combinations of data:

function idp() {

var isCreateForm = Xrm.Page.ui.getFormType() == 1;
if (isCreateForm) {

$.ajaxSetup({cache:false});
$(document.body).append("
A possible duplicate record was found, please review:
");

$('#name').focusout(function() {

var name = Xrm.Page.getAttribute('name').getValue();
var query = "/AccountSet?$filter=Name eq '"+name+"'";

var serverUrl = Xrm.Page.context.getServerUrl();

    if (serverUrl.match(/\/$/)) {
        serverUrl = serverUrl.substring(0, serverUrl.length - 1);
    }

    var ODataURL = serverUrl + "/XRMServices/2011/OrganizationData.svc" + query;

    $.ajax({
        type: "GET",
        contentType: "application/json; charset=utf-8",
        datatype: "json",
        url: ODataURL,
        beforeSend: function (XMLHttpRequest) {
            XMLHttpRequest.setRequestHeader("Accept", "application/json");
        },
        success: function (data, textStatus, XmlHttpRequest) {
           var entities = data.d.results;
    $.fx.speeds._default = 1000;
    $(document).ready(function() {
        $("#dialog").dialog({
            autoOpen: false,
            show: "blind",
            hide: "explode",
            modal: true
        });

    });
if(entities.length > 0 ) {
  for( i=0; i< entities.length; i++)
  {
     var entity = entities[i];
}    

var entityUrl = "main.aspx?etn=account&pagetype=entityrecord&id=";
$(document).ready(function() {
                             $("#link").empty();
                             $("#link").append(document.createTextNode(entity.Name));
                             $("a#link").attr("href","/"+entityUrl+"%7B"+entity.AccountId+"%7D"+"");
                             $('#dialog').dialog("open");
});
          
}

        },
        error: function (XmlHttpRequest, textStatus, errorObject) {
            alert("OData Execution Error Occurred");
        }
    });


});

}

}