Pages

Thursday, August 4, 2011

CRM 2011 Contact Image alternative approach

In light of my former post about options for embedding a contact image (or for that matter embedding any other type of image into a CRM form), I thought I'd highlight another, perhaps better, approach.

The former approach is a more centralized/controlled way of adding images and it dictates that the image file being added adhere to a certain given format (e.g. in order to point to the Bob Jones image when opening the Bob Jones form, I need to ensure that I have a "BobJones.gif" file on the server or perhaps "bjones_abc.com.gif" or some other derivation from the contact record so that I can link to the file when the form loads). Therefore adding images using this approach would presumably be given to an administrator user rather than being "democratized".

The other approach is to utilize the SilverLight control that can be found in codeplex. Kudos is also obviously due to the creator of this little add on.

Using this utility, any user can add an image to the contact form and the image is simply stored as an image in the Notes of the contact. A more decentralized approach and indeed a very slick alternative!



CRM 2011 Check if URL/file exists

We had a requirement to display a contact image along with the contact record in CRM. There are ample examples of how to go about doing this by either using a file on the server or a web resource. The following is a jscript snippet of how to go about adding an image referencing a file on the server (in this case the file should be placed in a ContactPics folder under the ISV folder. This could very easily be adapted to point to an image added as a web resource which is probably a better approach for CRM 2011.



function ContactPic(filename) {
    var picIframe = Xrm.Page.getControl("IFRAME_Pic");
    var src = picIframe.getSrc();
    var url = server + "/isv/ContactPics/" + filename;
    picIframe.setSrc(url);
}

The result should be something like this:


But what happens if the file does not exist neither as a web resource nor as a file on the server? In that case, it would be preferable to present a "No Image" default image or perhaps to hide the image altogether rather than showing a broken link. The challenge though is how do you detect that the link is broken in order to do so? Jscript does not allow you to interact with files on the server (due to security considerations) so performing a simple "file exists" check is not as simple as it might first seem.

The solution that I found to this issue was to detect a 404 error via a http request of the URL. As follows:

function UrlExists(url) {
    var http = new XMLHttpRequest();
    http.open("HEAD", url, false);
    http.send();
    return http.status != 404;
}


And now the ContactPic function can be updated to first test the URL and if it is broken to replace it with a default NoPic.gif image.

function ContactPic(filename) {
    var picIframe = Xrm.Page.getControl("IFRAME_Pic");
    var src = picIframe.getSrc();
    var url = server + "/isv/ContactPics/" + filename;
    if (!(UrlExists(url)))
        url = server + "/isv/ContactPics/NoPic.gif";
    picIframe.setSrc(url);
}



Tuesday, August 2, 2011

CRM 2011 Ribbon Buttons: Use Case scenario

My two previous posts summarized how to go about adding a custom ribbon to a CRM 2011 form. I thought I'd round the topic out by providing a scenario of how these concepts might be applied.

For the sake of this example, let's say that you want to have two buttons on your contact ribbon. One to perform some "Add" logic to add a contact to some list and a second to perform "Remove" logic to remove the contact from the list. The requirements would therefore be as follows:

  • The Add button should execute the "Add" custom function
  • The Remove button should execute the "Remove" custom function
  • The "Add" button should only be enabled when the contact is not already in the list (we could also hide the button but visually it might be more appealing to disable rather than hide the button)
  • The "Remove" button should only be enabled when the contact is already in the list
  • After clicking "Add" to add the contact list, the "Add" button should be immediately disabled and the "Remove" button should be enabled. And vice versa.
  • Both the Add and Remove button should only be displayed on the contact update form and not the contact existing form

In order to achieve the above you would apply the concepts mentioned in the previous 2 posts. Namely:

  1. Add 2 ribbon buttons - One for the Add function and one for the Remove function
  2. The "Add" button should call a custom jscript function that will execute some jscript logic to add the contact to a list
  3. The "Remove" button should call a custom jscript function that will execute some jscript logic to remove the contact from the list
  4. Add EnableRule sections for each button to control when these buttons are enabled/disabled
  5. The "Add" EnableRule section should call a custom jscript function that will perform some logic to determine whether the contact is in the list. It if is it will return false (i.e. disable "add" button as it is already in the list) otherwise it will return true (i.e. enable "add" button as it has not yet been added to the list)
  6. The "Remove" EnableRule section should similarly call a custom jscript function. In fact, in our example as the logic for displaying the "Remove" button is the complete inverse of display the "Add" button (i.e. when "Add" is enabled "Remove" should be disabled and vice versa), we can reference the same custom function as for the "Add" EnableRule and just invert the result (InvertResult="true").
  7. Add a "Xrm.Page.ui.refreshRibbon();" command to the end of custom functions that are responsible for adding/removing the contact from the list. This will ensure that the display rule is executed after the action has been performed which will result in the "Add" and "Remove" buttons being enabled/disabled as necessary.
  8. Add DisplayRule sections for each button to control when these buttons are displayed on the form
  9. In both cases, the DisplayRule section should just have a "<FormStateRule State="Existing"/>" entry which will instruct the buttons to only show on the Update form.

And that should be it!

CRM 2011 EnableRules and DisplayRules

My former post provided a visual overview of adding a button to a CRM 2011 form ribbon. We will now take this one step further by exploring the EnableRules and DisplayRules options. Simply stated these rules control the  enabled/disabled and show/hide behavior of the custom ribbon. This is important because the button may not be always relevant on the form being edited and this provides you with an ability to manage this.

Please refer to the screenshot below.




  1. EnableRules/DisableRules - These should be added to the CommandDefinition section of the customization file. There must also be a corresponding entry in the RulesDefinition section of the customization file.
  2. CommandDefinition EnableRule Id - Add an id here that uniquely identifies the rule that you are adding
  3. CommandDefinition DisplayRule Id - Add an id here that uniquely identifies the display rule that you are adding 
  4. RuleDefinitions EnableRule Id - This should match the EnableRule Id added in step #2.
  5. RuleDefinitions EnableRule CustomRule - This once again references a custom jscript function that will determine whether to enable or disable the button. I chose to reference the "default" contact library but this could be any jscript library.
  6. RuleDefinitions DisplayRule Id - This should match the DisplayRule Id added in step #3. 
  7. RuleDefinitions DisplayRule FormStateRule - This tells the form that the button should only be displayed on "Existing" forms i.e. the update as opposed to the create form.
  8. Function CustomEnableRule - The function in the example above must be created in the relevant jscript library and should match the FunctionName from the CustomRule section
If there were more "involved" considerations for the DisplayRule, we could of course have also created a custom jscript function to allow for greater manipulation of this rule. Refer to the CRM SDK for more configuration options.

Adding a Form Ribbon Button in CRM 2011

In CRM 4.0 it is possible to add a button to the body of a CRM form and there were many good reasons to do so. While this is still possible in CRM 2011, I would argue that it's no longer relevant with the introduction of the ribbon interface which allows a lot more granular control over the behavior and function than was available using ISV.config in CRM 4.0.

There are a number of good articles that walk through the technical process of adding a ribbon button that you can refer to. The following is a high level visual representation of adding a button that executes a custom action that should hopefully bring this all together succinctly. This article assumes you have read through some of the other literature that describes how you go about exporting, identifying, and editing the entity customization file that you wish to add a button to.

Please refer to the screenshot below.



The following are some of the more important sections of the edits that need to be made:

  1. CustomAction Id - Add an id here that uniquely identifies the custom action you are adding
  2. CustomAction Location - Identifies the ribbon to update. If you are updating an account, it will start with Mscrm.Form.account, if you are updating a lead it will start with Mscrm.Form.lead etc.
  3. CustomAction Sequence - Identifies where in the ribbon it will appear
  4. Button Id - Add an id here that uniquely identifies the button you are adding
  5. Button Command - Add a command name
  6. LabelText/Tooltips - Any descriptive text
  7. TemplateAlias - Defines how the button appears although I haven't delved very deep into this one yet. Default to "01". 
  8. Images - Reference 16 and 32 icons that you should add as a web resource to your environment (optional)
  9. CommandDefinition Id - This should match the Button Command referenced in step #5. 
  10. Command Definition Actions - This section defines the action to take when clicking the button. There are various actions that can be taken. The first example is commented and simply would take the user to a web page when clicked. The second example is a reference to a custom jscript function defined in the form jscript. I chose to reference the "default" contact library but this could be any jscript library.
  11. Function HelloWorld - The function in the second example above must be created in the relevant jscript library and should match the FunctionName from the CommandDefinition section
  12. Xrm.Page.ui.refreshRibbon - This is a command that you can optionally add to jscript. Some times after you click a ribbon button, you will want to disable that button or perhaps enable another button on the ribbon. By callling this command at the end of your jscript function, you instruct the ribbon to refresh and re-execute any of the Enable and Display rules to control the appearance of your button which I discuss in my next post.

That's it. Now when you click the ribbon button, you will receive a "Hello World" alert prompt.

That's a brief introduction to the topic. Refer to the CRM SDK for more configuration options.

Thursday, July 28, 2011

CRM 2011 OnClick Events

My former post highlighted the fact that the 4.0 syntax (unsupported though it was) no longer works in CRM 2011 and in fact has a lot more nefarious side effects than just not working as it should...

So how can the OnClick event be replicated in CRM 2011? The inspiration for my answer was provided from this post. I took the example that was provided and stripped it down to the following function:


function RegisterOnClickEvent(attr, fn) {
var e = document.getElementById(attr);  
    var f = "var click=function() { " +  
              fn + "(); " +  
" };";  
  
    eval(f);  

    // Attach to click event  
    e.attachEvent("onclick", click, false);  
}


Thereafter all you need to do to register an OnClick event for a bit field is to pass the following function call:

RegisterOnClickEvent("attribname","functionname");

CRM 2011: Error on page

While upgrading a CRM 4.0 environment to CRM 2011, I had to contend with the "Error on page" issue. That is, there was something in the jscript of the page that CRM was not liking which caused the page to render as with the "Error on page" message when loading and consequently with the "Microsoft Dynamics CRM has encountered an error" message when exiting the form.


I was further perplexed by the fact that this error did not appear to have anything to do with the form jscript as I disabled all onload and onchange events and yet the error did not go away. However after additional testing it did indeed appear to be linked to the jscript as when I cleared out the jscript of the form (as opposed to just disabling it) the error went away. Why the jscript should be affecting the form in such a way even when it is disabled is beyond me. It seems to defeat the purpose of being able to disable the jscript. But this is the first lesson from this exercise - jscript can affect form rendering even when it has been disabled. Maybe Microsoft will fix this in a future release.

Ok. So having determined that jscript was indeed the culprit the hunt was on to determine exactly which piece of jscript was throwing the form rendering off. This was a process of elimination whereby snippets of jscript would be removed until the offending jscript could be determined.

And what did it come to...?

I am sure this is not the only scenario which can result in this error but in my case it was because we had configured an on-click event for a field in the form. The 4.0 syntax of crmForm.all.field1.onclick = function() {} was troubling the application.

Once this had been removed the error went away... as did the cloud that was hanging over my head.