Wednesday, July 8, 2009

Dynamics CRM 4.0 Outlook client and SSL offload issues for IFD users

With my companies on-premise Dynamics server we use ISA for the SSL offloading and routing to the IFD server for external users. Another reason we do this is for the host header rewrite capabilities of ISA, since we named our Dynamics organization as the same as our company name (I'm sure many people do this). We didn't want to see as the browser url, so we picked something more suitable like so that its easier for the end user to remember and just makes more sense.

The problem that this creates, is when configuring the CRM Outlook client to use https for the external server, the SSL offload is happening at ISA. So the Dynamics server doesn't see it as an SSL connection during discovery and reports back that the URL's to the Dynamics services are normal Http. This works fine if you also expose non SSL traffic to your IFD server, but in our case we don't and do a 302 response to https. You will get this error message when you open Outlook off the network if you are set up in a similar fashion:

Fortuntely we just need to modify a few registry keys where the server url is stored to fix this. Using Registry Editor (regedit.exe), browse to HKEY_CURRENT_USER\Software\Microsoft\MSCRMClient

The two keys you will need to modify and add the https to are WebAppUrl, ServerUrl, ExtranetServerUrl, and ExtranetDiscoveryUrl.

After making the registry changes, launch Outlook and everything should connect up just as expected.

Monday, June 1, 2009

Overriding and Filtering Multiple Record Lookup Form for Microsoft Dynamics CRM 4.0

Warning: This will require some javascript and html coding knowledge, and one of Dynamics javascript files must be modified for this to work. Make sure you make backups of any files before modifying them.

One of the big limitations in Dynamics, is the inability to do any type of filtering or custom columns for the multi lookup form. I had a request from our support team to pre-filter the lookup results for contacts on the email forms To, CC, and BCC fields to only show contacts that are linked to the account that the regarding case is linked too. Without this they have to either open up the account and select contacts to find them, or do an advanced find lookup, both of which are a massive time waist for them and also prone to possible errors since they would have to then remember those contacts and go searching for them in the multi lookup form on the email. And we have far too many contacts and accounts for them to be expected to remember them by name when they are doing the lookup on the existing lookup form.

Unfortunately there is no built in or supported method for doing this, but I believe there is some third party tools out there to make this somewhat possible (Stunnware has something that looked useful and very well done). I decided to go down the road of trying to hijack the lookup window from Dynamics and display my own form, so that I can provide some highly customized functionality for their needs instead of trying to make something else work in our special way.

I first opened up the new email form in IE8 and attached the built in debugger (F12) and started profiling into what actually happens when you click the lookup glass image for the To and other multi lookup fields.

The To, CC, and BCC fields call the LookupObjects() method in wwroot\_static\_controls\Lookup.js which will build a url for what form to use. Since this does this based on a property on the field itself, I decided to use this to open my form instead and not require special code to handle my forms results. Here is the section of the LookupObjects() method we will take advantage of:

url = prependOrgName("/_controls/lookup/lookup");
url += lookupStyle;
url += ".aspx";
url += "?class=" + lookupClass;
url += "&objecttypes=" + lookupTypes;
url += "&browse=" + lookupBrowse;

As you can see, the lookupStyle is the property on the field we can change from “multi” to our own value (“multiaz” in my case) and then place an appropriately named file “LookupMultiAz.aspx” in that same directory (/_controls/lookup/) and it won’t require a modification of this method to get our custom form, or of the result handling.

Unfortunately we can’t just get away with modifying the fields lookup style attribute to point to our new form. Dynamics makes a call to the BuildFeatures() method in that same Lookup.js file to determine the sizing of the lookup window it’s about to open, and it will alert and stop your window from opening if it does not know about your new lookup style. So with a simple modification to the switch statement in the method, we can add our lookup style.
WARNING: This is not supported and you are modifying this file at your own risk! Make a backup copy first!

function BuildFeatures(lookupStyle) {
var oFeatures = new Object();

switch (lookupStyle) {
case "multiaz":
oFeatures.height = "460px";
oFeatures.width = "650px";
case "multi":
oFeatures.height = "460px";
oFeatures.width = "600px";
case "single":
oFeatures.height = "488px";
oFeatures.width = "600px";
case "subject":
oFeatures.height = "450px";
oFeatures.width = "500px";
alert(LOCID_LOOKUPSTYLE_NOT_SET + lookupStyle);
return null;

return oFeatures;

Next we need to make a new form/web page to replace the LookupMulti.aspx used by Dynamics. You must name this page Lookup[CustomStyle].aspx (replace [CustomStyle] with the name you chose in the previous steps, “multiaz” for me so “Lookupmultiaz.aspx”). In this page you will need to implement your own custom lookup and record selection to replace the Dynamics multi lookup form. Here is an example of the custom form that I designed for our support team based on their criteria:

To make your form work with Dynamics you need to pass back the records in the same format that Dynamics is expecting to get them in. Dynamics expects to get back the LookupItem object from LookupDialogs.js file (same location as Lookup.js), which you can re-use by adding a reference to it in your custom page. I chose to just copy the LookupItem() function to my form instead of referencing the file since I didn’t need anything else in there. As there is no real type safety in javascript, the object you return just needs to contain the correctly named properties.

function LookupItem() { = ""; = "";
this.html = "";
this.type = "";
this.values = null;
this.keyValues = null;
this.category = null;
this.ambiguousRecordsXml = null;

The only properties that need to be filled out for each LookupItem is:
id = the record id (guid)
name = name of the record (John Doe)
html = html to display the record

type = type code for the record (contact = 2, system user = 8, account = 1, etc)

Then add each LookupItem to the items property on an object and return it by setting the value to window.returnValue when ready.

var lookupItems = { items: new Array() };
var item = new LookupItem(); = ‘{479ECE53-099D-4fe5-92AE-AAA13659E7AC}’;
item.type = 2; = ‘John Doe’;
item.html = ‘<NOBR><IMG class=ms-crm-Lookup-Item alt="" src="/_imgs/ico_16_2.gif">John Doe</NOBR>’;

window.returnValue = lookupItems;

The other thing your form will need to handle is if the field already has values and the user opens your custom form, those values will be passed to your form by Dynamics using the dialogArguments property.

var args = this.dialogArguments;
for (var i = 0; i < args.items[i]; i++){
var recordHtml = args.items[i].innerHTML;
var recordId = args.items[i].getAttribute('oid');
var recordType = args.items[i].getAttribute('otypename');
//Do something with the record now

In your custom form you will need to query dynamics to retrieve records to present to the user, this can be done many ways and I wont get into that here. In my example I use a javascript library from Asenctium to interact with Dynamics that handles the SOAP mess, and the ExtJs framework for building my form and the interactions.

Happy coding!