The CRM Grid – A Microsoft CRM Blog

Greg Owens’ rose-tinted MS-CRM mumblings

Event execution order with ‘onbeforeunload’

Recommended JavaScript Book!

I'd also like to highly recommend this JavaScript book by Douglas Crockford - it will definitely improve the quality of your JavaScript development experience!


Recently I had a requirement to conditionally add some dynamic script to the onClose event for a CRM form. Given the flexiblility demanded by the requirements, it was not practical to write script in the form’s onClose() event hander in the CRM Form Properties window. Instead, I used Internet Explorer’s attachEvent method

The problem with the attachEvent method is that the collection of functions that are appended to the event are executed in “random order”. “Random” is rarely a desirable sequence  in my experience and in this case one cannot guarantee that a custom dynamic “validation check” (for example) will be executed before the default event handler (i.e. the one that may ask “Are you sure you want to navigate away from this page?”).

Alas a simple solution is at hand, thanks to this post made by “Adios” over at CodingForums.com. The function below will effectively inject your function call before the default event handler.  Obviously this function can be easily amended to deal with any type of event but the example  below is hard-coded to deal with the “onbeforeunload” event handler.

Define this function in your form onLoad script (or somewhere in your global code, if you have adopted a custom solution for centralising your JavaScripts):


function addbeforeunloadEvent(func)
{
    var oldonbeforeunload = window.onbeforeunload;
    if (typeof window.onbeforeunload != 'function') {
        window.onbeforeunload = func;
    } else {
        window.onbeforeunload = function() {
            oldonbeforeunload();
            func();
        }
    }
}

Then use the following snippet to insert your function ahead of the default or existing event handler:


//TODO: replace myFunctionName and myParameter list to match your custom function signature
addbeforeunloadEvent(function(){myFunctionName(myParameterList);});

Update Rollup 4 for Microsoft CRM 4.0 is available

More info and download here

SSRS – checking an external image exists

SSRS supports adding external images to your reports. This is useful if, like my client, you have images stored in a SharePoint Document Library. Using some commonly-found code for structuring their document libraries, most accounts have had an image called “main.jpg” uploaded. If “main.jpg” does not exist, there are good business reasons for this.

The client required a report which should include “main.jpg”, if it exists. Otherwise no image should be present at all. The problem is that SSRS is only aware of the URL to the image as a simple string. I used SQL to construct a URL string for each record, but SSRS can’t natively detect whether an image exists at this URL or not. There is a way around this, however. SSRS allows you to embed your own custom code in your report properties. The following code checks whether an image exists at a given URL and returns true or false. This code can be called from an image control’s “Hidden” property, or combined with an expression in the image controls “Value” property to manipulate the URL:


Public Function ImageExists(ByRef URL As String) As Boolean
'Create a web request
  Dim m_Req As System.Net.HttpWebRequest = System.Net.HttpWebRequest.Create(URL)   

  'Get a web response
  Try
    Dim HttpWResp As System.Net.HttpWebResponse = CType(m_Req.GetResponse(), System.Net.HttpWebResponse)
    If HttpWResp.StatusCode = System.Net.HttpStatusCode.OK
      Return True
    Else
      Return False
    End If
  Catch ex As System.Net.WebException
    If ex.Status = System.Net.WebExceptionStatus.ProtocolError Then
      Return False
    End If
  End Try
  Return Nothing
End Function

To use it, copy the code above to your report properties (Report > Report Properties… > Code), then after inserting an image control (with Image Source of “Web”), add the following code to the Hidden property (Image > Visibility > Hidden > Expression…):


=If (Code.ImageExists(FieldNameThatHoldsImageURL)=True)
  Then Return False
Else
  Return True

Any suggestions, improvements or alternative approaches are welcome!

MSCRM Update Rollup 3 is available

Just a quickie – it appears that Update Rollup 3 has been released for Microsoft Dynamics CRM 4.0.

This fixes about a dozen issues that are acknowledged in KB articles and more than 50 previously undocumented items too. The list of issues addressed can be found on KB961768

onLoad code not running

Another strange problem encountered and fixed today. The form onLoad code “suddenly” stopped working. I say “suddenly” because in fact this was a red herring and the problem turned out to be the result of a change. The symptoms were however unexpected.

Normally when a scripting error occurs in MSCRM, Internet Explorer will throw a script error dialog as the form loads (e.g. “There was an error with this field’s customized event.”):

scripterror

There was an error with this field's customized event

  Or alternatively a warning is shown at the bottom left of the Internet Explorer screen:

Error on page

Error on page

But on this occasion, there were no warnings. My first thought was to place a debugger statement into the code, but even after publishing this too failed to execute. I tried a simple alert() statement but this also failed. Odd.

Replacing all the code in the event handler with a simple alert() statement did work, so clearly this was a syntax problem, but very odd that it didn’t throw any error and in fact even blocked the debugger statement. If I were to delve deeper I’m sure I’d find that this is due to try…catch handling within the MSCRM ASPX pages…

In the end, the problem was caused by an htmlEncoded chevron character which had somehow been pasted into the javascript code (< ) while setting up a for loop.

Thanks due to Douglas Croxford’s JsLint for speeding the time to resolution somewhat.

Corrupted entity – NullReferenceException when publishing or exporting

A corrupted entity
I ran into a problem today with my client which frankly had me stumped. For some reason that I have yet to determine (though possibly related to a broken install of Update Rollup 2), the account entity got corrupted. We discovered this when somebody attempted to publish their changes to the account entity and ran into a “red” error dialog: “An error has occurred…please contact your system administrator”. This error was replicated if we tried to publish, delete any attributes from the entity or export the entity customizations. Not much scope for fixing the situation!

Troubleshooting…
After studying the server trace logs (thanks to CrmDiagTool4 and Michael Hoehne’s Trace Log Viewer for easing this process), the situation wasn’t much clearer. The underlying error was:


Request URL: http://localhost/MyOrgName/AppWebServices/SystemCustomization.asmx
Stack Trace Info: [NullReferenceException: Object reference not set to an instance of an object.]
at Microsoft.Crm.ObjectModel.OrganizationUIService.LabelLoaderAllLanguages.LoadMetadataLabel(Int32 entityType, String attributeName, ExecutionContext context)

I also did a SQL Trace using SQL Profiler on the server, but this didn’t really provide anything new at all.

So, when faced with a problem I can’t resolve myself, I turned to Google for help. I managed to find KB article 947096 which seemed very near to my problem, but sadly none of the resolution steps would help me. I then tried importing a known good copy of the account entity customizations but that failed too. At this point I looked back at the Trace Log and tried to determine what was going on “under the hood” prior to the failure…

It was clear from the logs that CRM was trying to pull in LocalizedLabel information for my entity attributes and form controls, however I couldn’t quite fathom out which attribute was causing the NullReferenceException (it seems that the last statement in the logs – MetadataProcessObject.ExecuteQuery – was successfully completing its SQL command and the following statement which was failing was not logging any parameters and therefore didn’t provide me with a “smoking gun”). In fact there were many calls to both CrmDbConnection.InternalExecuteReader and MetadataProcessObject.ExecuteQuery so clearly there was an interative loop going on. I didn’t know which mechanism within the CRM server black box was selecting the list of attributes to process, so I looked further back and found that this loop was likely being “triggered” by the FormXML property on the OrganisationUI view.

At this point everything clicked into place: the problem, somehow, was with the published version of my form (some of you may have realised this long ago). This form xml was being re-evaluated (for some reason) prior to every publish, export or delete request and then failing some integrity or logical check. Re-importing a known good copy would not help, since it would need to be published to take effect. I only had one option left – to break all the rules and manually amend the database in order to correct the corrupted FormXml property…

So here’s what I did:

Resolution
Took a backup of the current formXml property by running the following SQL statement within SQL Server Management Studio in the “_MSCRM” database (then right click on results tab and click “save as”…):


select organizationui0.ObjectTypeCode organizationui0.FormXml as 'formxml',
from OrganizationUI as organizationui0
where (organizationui0.InProduction = 1 and (organizationui0.ObjectTypeCode = 1))

Next I found my “good” copy of the customizations file. I identified the start and end node that was required in order to match the same format as the existing formXML property (the starting tags were <form><entity…>). Next I copied this xml to a new file and removed all tabs and new lines, to give a single continuous string.

I saved this xml file onto my CRM server then went back to SQL Management Studio and ran the following SQL to import this long string directly into the SQL table:


declare @xmlText varchar(max)
select @xmlText =(select * from openrowset (bulk 'c:\amendedformxml.txt',SINGLE_CLOB)x)
update dbo.OrganizationUI
set FormXml = @xmlText
where (InProduction = 1 and (ObjectTypeCode = 1))

This effectively “forced” my old formXML into a published state and magically fixed my problems. Further, once I clicked “Publish” following these steps, the formXML was consequently re-evaluated again and the hitherto unpublished customizations become published (as expected) and therefore effectively no information had been lost by importing the older xml.

Conclusion
So I still don’t know what caused this issue… I’d love to know if anyone else has had a similar situation. I’m not entirely comfortable with the way I had to fix the problem either, but then sometimes your hand is forced into doing things you don’t want to do. I’ll monitor the situation and let you all know if there are any repercussions. In the meantime, the usual caveats apply – the steps above are definitely unsupported and could definitely render your CRM installation inoperable, so use the steps above at your own risk!

Minor problem after installing MSCRM 4.0 Update Rollup 2

Edit: It seems that the issue below was limited to my client’s machine only. I’ve reinstalled Update Rollup 2 and the problem went away… The rest of this post is here for reference:

It seems that there is a small bug introduced It seems that my client has encountered an issue with Update Rollup 2 for Microsoft CRM. After installing, the form labels shown in the form designer are incorrectly reading from the published entity definitions, rather than the unpublished definitions. The result of this is that if you update a field label and click save, it appears not to have worked. If you ignore this apparent effect and publish your entity, lo! The field labels are indeed automagically updated after all.

Steps to reproduce:

  1. Open any entity for via Settings > Customization > Customize Entities > …
  2. Go to Forms and Views > Form
  3. Double-click any existing field and change the Label attribute then click OK
  4. At this point, the amend appears correctly
  5. Click the Save button on the form
  6. Note that your label amendment appears to have been backed out…(!)
  7. Close the form designer screen and from the entity record, click Actions > Publish
  8. Go back to the form designer via Forms and Views > Form
  9. Note that your label amendment has indeed persisted and is now also in production too

Edit: so we fixed this by removing UR2, rebooting, downloading UR2 afresh, reinstalling UR2 and rebooting again. Can’t imagine what failed – perhaps I had an early release of Update Rollup 2 with a bug – I seem to recall that it was silently reissued shortly after release.

Microsoft CRM Event Management Accelerator released!

Great news – the much anticipated CRM Accelerators are finally starting to be released!

Initially there were two releases available on PartnerSource only, but now more code is appearing on Codeplex too: http://www.codeplex.com/crmaccelerators - specifically, we can now get our hands on the first really exciting one – the Event Management accelerator. This doesn’t appear to have been publicised so well just yet so I thought I’d shout up!

At the time of writing, it is now possible to download the following:

  • Event Management (Codeplex only at present)
    “Ability to manage the planning, execution, tracking and reporting requirements for events…” including an example external website allowing delegates to register themselves on your events and reports to measure effectiveness of your events.
  • Notifications
    Subscriptions to business events (e.g. new leads for current user) which are delivered via RSS feeds
  • Extended Sales Forecasting
    Primarily, new reports to allow better visibility of sales forecasts, including individualised sales pipeline and per salesperson performance against forecast by time period

Happy playing!

Mail merge with CRM Web Client fails – cannot find data source

We ran into an issue last week where attempts to mail merge (specifically the “Print Quote for Customer” button) were failing. CRM would provide a Word document for download, but opening the document resulted in a warning:

Opening this document will run the following SQL command:

This message was followed with… no SQL command. Clicking on “Yes” to continue, presented the message:

Mail_Merge_<random numbers>.doc is a mail merge main document. Word cannot find its data source, .

Mail_Merge_.doc is a mail merge main document. Word cannot find its data source, .

No matter which templates were selected or which permissions were granted, the same error occurred.

This seemed to happy with machines that had the web client only (unconfirmed, but I believe this does not happen with the Outlook CRM client) and Office 2007 SP1.

A call to Microsoft support has verified that this is known issue, albeit undocumented for the public. It seems that Service Pack 1 for Office 2007 introduces an issue for mail merging from the web client. Apparently a hotfix is in the making but this is not being considered as a high-priority fix.

If you know of any workarounds let me know. If you have the problem yourself, get in touch with Microsoft and let them know so we can get a hotfix moved up their to-do list!

Debugging plug-ins in v4.0 (Updated)

(Updated 9th June 2009)

As you will know, the extensibility model for Microsoft CRM has changed in v4.0 and we now have a concept of plug-ins (instead of the callouts that were used in v3.0).

I’m not a particularly seasoned C# developer but having got a comfortable grasp of the language, I was struggling when it came to debugging my plug-in. I knew the general principles of debugging and thanks to the plug-in registration tool, could get my code to fire, but I couldn’t get it to debug. I can now and here’s what I did (note – no revelations here, I’m simply writing this for the benefit of other n00bs).

Please note, I still use Visual Studio 2005. I haven’t done this in any other version so there’s no point in me trying to write about it – please comment if you have and whether these steps differ.

  • So you’ve finished coding and are ready to deploy your assembly. Step one is to build your project via the Build… menu in VS.
  • Next you need to deploy your assembly to the development server. You’ll need to use the Plugin Registration Tool to do this. I usually opt to deploy to the database as this avoids me having to deal with “file in use” errors (see below).
  • In addition to deploying your assembly you must also place the debug symbols (.pdb file)  in  …\Program Files\Microsoft CRM\Server\bin\assembly. Once you’ve built your solution in Visual Studio, ensure that the latest copy of the .pdb file (look in your solution’s build directory) is copied to the aforementioned directory.  Every time you (re)build your  assembly you must copy the revised pdb file across.
  • After copying the pdb file, you’ll need to restart IIS using the iisreset command from the command prompt.  This is required so that the symbols can be read in (this step is also necessary sometimes in order to avoid “file in use” errors if you choose to deploy your assembly dll to disk) .  I usually add an iisreset command into my Post-Build script in Visual Studio, along with an xcopy command, to move the pdb file to the correct location after each build.
  • After running iisreset, you need to effectively “kick start” the CRM thread  by simply opening or refreshing any CRM page. This ensures that the w3wp process is available for the debugger to attach to.
  • The next step is to load your solution file up on the server. This of course requires Visual Studio to be installed on the development server. There may be alternatives to this approach (perhaps remote debugging or a test harness – see below) but I haven’t tried them.
  • With your solution open on the server, select Debug > Attach to Process and then select the w3wp.exe process from the the list. You may need to place a check in the “Show Processes from all users” and “Show processes in all sessions” in order to see w3wp.exe.
  • If you haven’t already done so, add some breakpoints to your code in VS by moving the cursor to the code you wish to break on and pressing [F9]. A red dot should appear in the margin.
  • Finally, go to CRM and do whatever is required (as per your plug-in registration) to fire your plug-in (i.e. create/delete/update an appropriate record)
  • The code should fire and reach your breakpoint in Visual Studio. You can step through the code a line at a time by press [F11] to advance to the next statement.

You might also be interested to hear that Akezyt Janedittakarn wrote on the MSCRM Team Blog about steps to aid the debug process using a test harness 

I’ve just found this article at sadev.co.za on how to debug CRM plug-ins remotely.

Older entries »