Originally published at http://goo.gl/C1n3Hw

If you have worked with the Dynamics CRM 2011 SDK you are probably very familiar with the Request/Response model messages in Microsoft.Crm.Sdk.Messages. As a developer trying to write good code I always want to wrap any service call in a Try/Catch statement to provide proper error handling. Another goal is to keep the code as neat as possible for when I – or someone else – has to go back and read it. Wrapping calls in Try/Catch statements increases the total lines of code it takes to implement functionality and makes the code more difficult to read.

Recently I was working on a project where I had several of these calls in a row: Execute a request, process the response, build a new request, execute, etc. etc. While I was looking at the code I realized that my catch routine was basically the same (format a message for the user and exit out of the program – in addition to sending a number of execution details to the tracing service). Since the code was getting very long, my first thought was to refactor each of these calls into its own method. While this approach would make my code a bit cleaner, it was still somewhat limited in value.

After thinking about the problem a bit more, I decided this would be a perfect opportunity to implement generics, extension methods, and delegates.

If you are unfamiliar with any of these topics, here is a super quick introduction:

  1. Generics allow us to create a method without having to know all the input types or the response type thus allowing the developer to specify them when calling the method.
  2. Extension methods allow us to create static methods against an existing class without having to inherit to a new class thus we do not disturb any code already relying on the class we want to extend.
  3. Delegates let us take a method (that matches the specified signature) and pass it as a variable.

You can find out more about each of these concepts in the MSDN documentation links provided.

Before we get too far into the details we should review the issue we are trying to resolve. Here is a very basic CRM plug-in that executes a WhoAmI request and gets a WhoAmI response. As I count it there are 6 statements with the try/catch but not including the PluginSetup (see my previous post athttp://goo.gl/lEaa9), to complete the request. It may not seem like a lot, but in the real-world those calls also have logging and the request probably has actual properties that need to be set. No matter what request message you use the basic pattern will remain the same.

public void Execute(IServiceProvider serviceProvider) 
{ 
    var p = new PluginSetup(serviceProvider);
    var req = new WhoAmIRequest();
    WhoAmIResponse response = (WhoAmIResponse)p.Service.Execute(req); 

    try
    {
        response = (WhoAmIResponse)p.Service.Execute(req);
    }
    catch (Exception ex)
    {
        // Do some error handling...
        throw new InvalidPluginExecutionException(ex.Message);
    }

    //Do something with the response...
    
}

What if we could achieve the same functionality with the following code?

public void Execute(IServiceProvider serviceProvider) 
{ 
    var p = new PluginSetup(serviceProvider); 
    var req = new WhoAmIRequest(); 
    var response = p.Service.Execute<WhoAmIRequest, WhoAmIResponse> (req, GotError); 

    //Do something with the response! 

} 

We are now down to 2 statements. Your code just got cleaner and became easier to write.

So now let me show you how we did it.

public static class GenericCRMRequest 
{
    public delegate void ErrHandler(Exception Ex); 

    public static RESP Execute<REQ, RESP>(this IOrganizationService Service, REQ Request, ErrHandler Err) where REQ : OrganizationRequest where RESP : OrganizationResponse 
    {     
        RESP response = null; 
        try 
        { 
            response = (RESP)Service.Execute(Request); 
        } 
        catch (Exception ex) 
        { 
            if (Err != null) Err(ex); else throw; 
        } 
        
        return response; 
    } 
} 

The first thing we do is declare a delegate called ErrHandler. This will allow us to pass in a method that can be called when an exception occurs. In my demo below I just throw the error as an InvalidPluginException. In my real-world application the exception is logged and then a user-friendly message is sent to the user.

We can implement as many of these methods as we need and we can do so anywhere in our code. So long as it matches the signature, void return and one parameter of type Exception, any static method will work. Btw, you could certainly expand this to pass request details to the error handler and log them. In my application I pass an ILogging instance (which I’ll discuss in a future post) in addition to the Exception that allows me to write to a log file, the plugin tracer service, LOG4NET, etc.

protected static void GotError(Exception ex) 
{ 
    throw new InvalidPluginExecutionException("We got an Error in ExecuteCrmRequest - Please tell someone!"); 
} 

The method itself is generic (meaning when called we have to define everything – within the constraints defined by the where clause and the delegate signature) and is an extension toIOrganizationService, this means that we’ll be able to call this method from any instance of a class that implements the IOrganizationService interface. By making it an extension method (the requirement being that it be a static method in a static class) it can be called without either having to pass a IOrganizationService object. In addition, since we named the method Execute it will overload the existing Execute method making for cleaner easier to read code.

public static RESP Execute<REQ, RESP>(this IOrganizationService Service, REQ Request, ErrHandler Err) where REQ : OrganizationRequest where RESP : OrganizationResponse 

My hope is that you’ll take this and expand on it. While the CRM SDK is really well done we can always do things that allow us to work more efficiently while creating more manageable code. You’ll appreciate it, your colleagues will appreciate it, and your clients will appreciate it.

Here is all the code in this blog article together in one place. Please use and expand on this concept to standardize your development, save time, reduce errors, and produce easier to read code.

public static class GenericCRMRequest 
{
    public delegate void ErrHandler(Exception Ex); 
    
    public static RESP Execute<REQ, RESP>(this IOrganizationService Service, REQ Request, ErrHandler Err) where REQ : OrganizationRequest where RESP : OrganizationResponse 
    {     
        RESP response = null; 
        try 
        { 
            response = (RESP)Service.Execute(Request); 
        } 
        catch (Exception ex) 
        { 
            if (Err != null) Err(ex); else throw; 
        } 
        
        return response; 
    } 
} 

public class CRMRequestPluginDemo : IPlugin 
{ 
    public void Execute(IServiceProvider serviceProvider) 
    { 
        var p = new PluginSetup(serviceProvider); 
        var req = new WhoAmIRequest(); 
        var response = p.Service.Execute<WhoAmIRequest, WhoAmIResponse> (req, GotError); 

        //Do something with the response! 

    } 

    protected static void GotError(Exception ex) 
    { 
        throw new InvalidPluginExecutionException("We got an Error in ExecuteCrmRequest - Please tell someone!"); 
    } 
}
Categories: Dynamics CRM