Kids, don't try this at home!

Tips & Tricks for C#, ASP.NET and CRM

  • A bit of syntatic sugar for CRM 2011 LINQ

    We've been using XrmLinq for our CRM 4 developments and we've gotten use to that syntax, the new LINQ provider in CRM 2011 is a bit different but thanks to extension methods and generics we can make it look the same as XrmLinq. Main reason for this is to port existing code over to CRM 2011 with minimal efforts.

  • How to change the grid icons dynamically

     
    Here is an unsupported but a harmless customisation you can do to Dynamics CRM in-order for you to change the grid icons dynamically. In the example above I wanted to show whether an account has been locked or not (keep an eye out for my next blog post on how you can set privacy settings on records/child records per user and per role)

    The standard grids in Dynamics CRM has a css class defined called "ms-crm-List-Data", if you have a look at the /_grid/AppGrid.css.aspx you'll see that, that class has a behaviour defined, this is what we'll use to swap out the icon.

    For example
    .ms-crm-List-Data
    {
    table-layout: fixed;
    width: 100%;
    behavior: url(/_static/_grid/appgrid_defaultdata.htc) url(/isv/magnetism/project/swapicon.htc);
    }

    Highlighted in bold is our custom behaviour script, which looks something like this:

    <public:component lightweight="true">
    <
    public:attach event="ondocumentready" onevent="initSwapIcon()"/>

    <
    script language="JavaScript"></script>
    <
    script type="text/javascript">
    function initSwapIcon() {
        // only apply it to known entities + xyz crm
        if (typeof (this.oname) != "undefined" && window.location.href.toLowerCase().indexOf("xyz") > 0) {
       
    if (this.oname != "1") { return; } // 1=account
           
    for (var i = 0; i < this.rows.length; i++) {
           
    if (typeof (this.rows[i].oid) != "undefined") {
               
    this.rows[i].cells[1].innerHTML = "<img src=\"" + "/isv/magnetism/project/swap-icon.ashx?id=" + this.rows[i].oid + "&type=" + this.oname + "\" />";
            }
        }
    }
    }
    </script>
    </
    public:component>

  • Pre-filter the Dynamics CRM Form Assistant

    Time for another trick...

    While trying to reduce as many clicks as possible one customer insisted that they want the form assistant pre-filtered, most of you are aware that this is not supported. Google Bing said it's unsupported and I couldn't see any useful info so opened up the IE Dev Toolbar and found that there are 2 elements; a textbox for searching via form assistant and the search icon (findValue and btnGo), now all that's needed is to put our pre-filtering text into it and force click that button!

    On the form onLoad event

  • Programmatically reuse Dynamics CRM 4 icons

    The team that wrote the dynamics crm sdk help rocks!

    I wanted to display the same crm icons on our time tracking application for consistency, so I opened up the sdk help file, searched for 'icon', ignored all the sitemap/isv config entries since I know I want to get these icons programatically, about half way down the search results I see 'organizationui', sure enough that contains the 16x16 (gridicon), 32x32 (outlookshortcuticon) and 66x48 (largeentityicon) icons!

    To get all the entities, execute a retrieve multiple request.

    RetrieveMultipleRequest request = new RetrieveMultipleRequest
    {
        Query = new QueryExpression
        {
            EntityName = "organizationui",
            ColumnSet = new ColumnSet(new[] { "objecttypecode", "formxml", "gridicon" }),
        }
    };
     
    var response = sdk.Execute(request) as RetrieveMultipleResponse;

    Now you have all the entities and icons, here's the tricky part, all the custom entities in crm store the icons inside gridicon, outlookshortcuticon and largeentityicon attributes, the built-in entity icons are stored inside the /_imgs/ folder with the format of /_imgs/ico_16_xxxx.gif (gridicon), with xxxx being the entity type code. The entity type code is not stored inside an attribute of organizationui, however you can get it by looking at the formxml attribute objecttypecode xml attribute.

    response.BusinessEntityCollection.BusinessEntities.ToList()
        .Cast<organizationui>().ToList()
        .ForEach(a =>
        {
            try
            {
                // easy way to check if it's a custom entity
                if (!string.IsNullOrEmpty(a.gridicon))
                {
                    byte[] gif = Convert.FromBase64String(a.gridicon);
                }
                else
                {
                    // built-in entity
                    if (!string.IsNullOrEmpty(a.formxml))
                    {
                        int start = a.formxml.IndexOf("objecttypecode=\"") + 16;
                        int end = a.formxml.IndexOf("\"", start);
     
                        // found the entity type code
                        string code = a.formxml.Substring(start, end - start);
                        string url = string.Format("/_imgs/ico_16_{0}.gif", code);


    Enjoy!

  • Tax rules for Dynamics CRM 4

    Now that Tax (G.S.T) is about to change here in New Zealand it's probably a good time that you check with your dynamics crm implementor/developer if you're going to get pinged for changing 12.5% to ...

    We've created an addon for dynamics crm that automatically calculates tax. It works on any entity (even custom ones), you can specify different rates, different rates for different currencies and/or combinations of both on any entity as long as there is an amount and a tax field.

    For example, take a look at the screenshot below, we've configured the tax rules plugin to run on an invoice line item.


    Future proof your dynamics crm by contacting us and installing this plugin!

  • CRMAppPool number of worker processes and plugins

    I recently came across some strange behaviour in dynamics crm. It seems that if you increase the number of worker processes from 1 (default) to n and you have plugins running synchronously crm will throw access denied exceptions randomly when the load is high on the server.

    Unhandled Exception: *.CrmException:
      0x80048405
      Access is denied.
      Platform


    What seems to happen is a request comes into crm, it fires a plugin then when the plugin tries to make another call to crm (using context.CreateCrmService()) it fails, the reason I believe is this request gets routed through a different w3wp which is a whole different app domain.



    Workaround
       
    Keep the worker process count at 1 on the CrmAppPool