Thursday, April 24, 2014

TypeScript and Dynamics CRM 2013 – Part 2

Last time I gave a brief introduction to getting TypeScript and Dynamics CRM 2013 client extension to play well together. In this post I’m going to describe a way to utilize TypeScript for structuring and modularizing the client extension code.
A great benefit from TypeScript is, that it has semantics and syntax that is similar to that C#. TypeScript has classes with methods, properties and inheritance. There are modules, which are similar to namespaces. However, there are some quirks, that makes TypeScript behave differently to what a C#-coder would expect. Lets get back to those and start with a simple example.

Modularize the code

For this first example, lets recall the code snippet for previous post doing a simple field hide/show. The obvious would be to create a method in a class within a module, like below.

///<reference path="Xrm.d.ts">
module DKCRM {
    class HideField {
        hideField() {
            ...
        }
    }
}

There are two reason why that would not work.
  1. The class is internal to the module. Compare it to a private class in C#
  2. In CRM form events it is only possible to execute function by name, i.e. a class cannot be instantiated.
Luckily it is simple to fix those to issues. Just add export keyword for the class and add a static method to execute the logics.

///<reference path="Xrm.d.ts">
module DKCRM {
    export class HideField {
        static execute() {
            var instance = new HideField();
            instance.hideField();
        }

        hideField() {
            var phone: string = Xrm.Page.getAttribute('telephone1').getValue();

            if (phone == null) {
                Xrm.Page.getControl('fax').setVisible(false);
            } else {
                Xrm.Page.getControl('fax').setVisible(true);
            }
        }
    }
}

Getting it to work in CRM is then only a matter of uploading the generated JavaScript-file as a web resource and call DKCRM.HideField.execute function from the form event.

    Tuesday, April 15, 2014

    TypeScript and Dynamics CRM 2013 – Part 1

    This post is intended to be the first in a series of post about using TypeScript with Dynamics CRM 2013. It will focus on the very basics to get started.

    TypeScript definition for CRM2013

    One might wonder why Microsoft didn’t include a guideline to using TypeScript for writing Dynamics CRM 2013 client extensions. Afterall, TypeScript is a language they invented in an attempt to overcome some of the annoyances of Javascript for .NET developers. And it is an incredibly great attampt, I might add :)
    Luckily a TypeScript definition file for CRM 2011 has been created by Damian Sinay (see it here http://crm2011typescript.codeplex.com/). That required only minor reworking to become CRM2013 compatible. The CRM2013 definition file is on GitHub (https://github.com/sduck/Crm2013TypeScript).

    Using TypeScript for CRM client extensions

    Lets say we want to create a small script, that hides the fax field if phone number is empty. This would pretty much end up in this little code snippet
    ///<reference path="Xrm.d.ts" />
    
    function hideField() {
        var phone: string = Xrm.Page.getAttribute('telephone1').getValue();
    
        if (phone == null) {
            Xrm.Page.getControl('fax').setVisible(false);
        } else {
            Xrm.Page.getControl('fax').setVisible(true);
        }
    }

    In this simple example there are very little differences between TypeScript and JavaScript. Only the first line with a reference to the definition file and the type definition of the variable sets it out.

    However, writing the code reveal one huge benefit of using TypeScript over JavaScript. I had nice intellisense to help autocomplete the code. This alone makes writing code faster and finding the right  methods easier.

    image

    Deploying a TypeScript client extension

    When writing TypeScript, the output will eventually be a JavaScript file. Depending on your IDE and setup this file will be created automatically and it will be named the same as the TypeScript-file. Only will the extension of the compiled file be .js.

    Locate that file and deploying to CRM2013 is just as deploying any other JavaScript extension.


    In the next post, I will be discussing how to use TypeScript for structuring the code.

    Sunday, July 12, 2009

    Cannot add users in CRM 4.0 organization

    In a CRM 4.0 multi-tenancy environment I recently experienced problems when trying to add new users to one of the organizations. The error message was pretty non-informative – just a error dialog telling that: ”An error has occurred”.

    As I experienced this in the test environment, I had no thought on turning on the CRM Server Trace. After some digging on the trace files I found another pretty unusable error message. This time stating that:

    DirectoryServicesCOMException: The server is unwilling to process the request. (Exception from HRESULT: 0x80072035)

    Thus, I had to do some thinking in what the cause could be. I came to realize, that the user I was trying to add belonged to a different domain than the CRM server. So I tried adding a user from the same domain, which succeeded without any problems. However, I had already added users from that other domain implying that a complete lag of permission was not the issue here.

    The next thing i remembered was that the users I was trying to add actually was already added as user in another organization on that same CRM server. Could it be, that this had to do with limited permissions that prohibited CRM from re-adding the CRM AD-groups to users in that other domain. When installing CRM I read an article on the minimum required permission for doing the installation (http://support.microsoft.com/kb/946677). It contains a section on Auto Group Management  - should CRM added AD groups to users automatically. I found out that Auto Group Management can be turned off by a registry key:

    HKLM\Software\Microsoft\MSCRM\AutoGroupManagementOff

    When setting this DWORD regkey to 1 and trying to create the users again, the operation succeeded..

    Friday, June 26, 2009

    Closing CRM Case window upon resolve

    This will be my first blog post on MSCRM tricks I've learned throughout my experience. It arose from the simple usability question from a customer of mine: "Why do I have to close the case windows myself after resolving it?".
    It filled my mind for a few days, because he had a point. The case form is after all read-only once resolved. And fortunately I came up with a simple and easily implementable solution with a simple onload JavaScript:
    if (window.opener) {
      var resolveMenuItem = document.getElementById('_MIresolve');
      if (resolveMenuItem) {
        resolveMenuItem.action = 'window.opener.openCaseWindow = window; resolve();';
      }
    
      try {
        window.opener.openCaseWindow.close();
        window.opener = null;
      }
      catch(e) {}
    }


    The above JavaScript located the Resolve menu item (from the Actions menu) and changes the action on that if it exists. The action is prepended with a simple line that stores a reference to the current case window on the opening form, i.e. the main MSCRM window, an account form or what ever window the case was opened from. Finally it tries to close the window to which a reference has been stored.


    Hence, when you click the resolve case menu item, a window reference will be save. When the standard MSCRM resolve dialog is filled in and ok is pressed, the case form will be submitted to persist the resolve data and once the form load again it will trigger the action to close itself.


    Note that this will note work if a case is opened from a link in e.g. an email.

    AddThis