Microsoft CRM Code Injector for HTTP Handling

crmlogo1

A HTTP Handler intercepts HTTP requests as they are preformed for a particular application; in this case it is a Microsoft Dynamics CRM application. Our HTTP Handler performs code injection in the form of JavaScript; there are 5 parts to the project.

1. Web.config setup

2. Base filter classes

3. Element Extension

4. JavaScript logic files

5. CSS extension files

Let’s take a look at what each one of these 5 parts do.

Web.Config setup

By adding an entry to the <httpModules> section of the Web.Config for the CRM application something like \Inetpub\crmroot\Web.Config each time a HTTP request is preformed we can preform logic via a DLL we will build from the Base filter classes and Element Extension logic (Items 2 and 3 above).  To configure this entry we would insert a line in the <httpModules> section like the following:

<httpModules>

<add name=”ExtensionModule” type=”eCRM.Customize.ElementExtension, eCRM.Extension” />

</httpModules>

eCRM.Extension is the name of the DLL we will create and eCRM.Customize.ElementExtension is the actual name of the IHttpModule class within our project.

Base filter classes

There are two classes that make up the support for our ElementExtension.  The ElementExtension will essentially inject a CSS behavior into the page being processed by the HTTP server (IIS).  The first part is BaseFilter.cs  an abstract class which is simply a System.IO.Stream, and the second part is ElementInsertFilter.cs which inherits the BaseFilter and does the actual work of inserting the CSS behavior.  There isn’t likely any changes that will need to be made to the BaseFilter abstract class, but there might be modifications needed for the ElementInsertFilter.  The ElementInsertFilter is basically a map that tells the code injector logic where to inject the CSS link or, in some cases but not our sample here, you might inject HTML after the <BODY> tag or in a certain <DIV> tag etc….

//..find the </head> element

match = new Regex( “</head>”, RegexOptions.IgnoreCase ).Match( this._buffer.ToString() );

if( match.Success )

{

//..insert the stylesheet element just before the </head> element

this._buffer.Insert( match.Index, this._element );

}

In the previous partial code snippet, we instruct our code injector to insert the CSS link just before the closing </head> tag.  It would be possible to inject JavaScript directly without using the CSS element. It is also possible to inject HTML.  If this were the case you would need to modify the ElementInsertFilter filter with additional logic used to determine where to inject the HTML or JavaScript.

Element Extension

The  ElementExtension.cs simply analyzes the HttpContext passed in to determine the file path.  In the following structure and in the class in the sample project you will need to add one string constant and one FilePath check per element or page you wish to handle.

//Define a string constant to hold the path and file name of our CSS document.

string sfa_accts_edit = “<link rel=\”stylesheet\” type=\”text/css\” href=\”/_oth/HTC/sfa_accts_edit.css\”>” + Environment.NewLine;

HttpContext context = ( ( HttpApplication ) sender ).Context;

//If the path is what we are looking for pass the CSS string to the ElementInsertFilter class.

if (context.Request.FilePath.StartsWith(“/sfa/accts/edit.aspx”, System.StringComparison.OrdinalIgnoreCase))

{

context.Response.Filter = new ElementInsertFilter(context.Response.Filter, sfa_accts_edit);

}

JavaScript logic files

An HTC is an HTML file that contains script and a set of HTC-specific elements that define a component.  We are using HTC files here to store the JavaScript behavior we want our HTTP handler to inject at runtime.    You will need to include the component tag at the beginning of your HTC file script.

<public:component lightweight=”true”>

<public:attach event=”ondocumentready” onevent=”Init()” />

</public:component>

The component tag tells the page processor that we want the JavaScript code logic to be loaded when the Initialization or Init() event is fired.

We might do a simple onload of the form even like this:

function Init()

{

window.onload=OnDocLoad();

}

In another case we might attach an event to a control on the page like this:

function Init()

{

window.document.forms( “crmForm” ).elements( “customertypecode” ).attachEvent( “onchange”, OnCustomerTypeChange );

}

In both cases, we attach a  JavaScript function we have created and attach it to a form or control event.  In this example, we are going to hide the built-in CRM help menus so we will attach to the main form onload event or   window.onload and call the following function:

function OnDocLoad()  

{

var helpMenu = document.getElementById(‘mnu_about’);

helpMenu.style.display = ‘none’;

var helpMenu = document.getElementById(‘mnu_helpUpdates’);

helpMenu.style.display = ‘none’;

var helpMenu = document.getElementById(‘mnu_crmLive’);

helpMenu.style.display = ‘none’;

var helpMenu = document.getElementById(‘mnu_adminGuide’);

helpMenu.style.display = ‘none’;

}

CSS extension files

The CSS file is very simple and has one small, but critical job.  It adds a behavior which attaches the HTC file to the page request being handled by the web server (IIS).  This is done with just a couple line in the CSS file.

body

{

behavior: url(activities_attachment_edit.htc);

}

As you can see the injector concept is a much better option than modifying CRM base pages.

Regards,

Brenden MVP


Advertisements

4 thoughts on “Microsoft CRM Code Injector for HTTP Handling

  1. Really like the concept here but a bit confused on what steps you’re taking to create the BaseFilter and ElementFilterInsert classes. Is there documentation somewhere on that?

  2. Hi,

    Can you send me the sample file for this blog? I am trying to do something like this in my project also.
    Thank You.

    Regards,
    Thor

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s