locked
Visual Studio Solution Template: Exception Handling best practice? RRS feed

  • Question

  • I'm developing plugins for CRM 2011 using the Visual Studio Solution template provided by the SDK, but I'm not entirely sure how to properly handle the exceptions using it. The base plugin class in the template, which my plugins need to derive from, does this:

                catch (FaultException<OrganizationServiceFault> e)
                {
                    localcontext.Trace(string.Format(CultureInfo.InvariantCulture, "Exception: {0}", e.ToString()));
    
                    // Handle the exception.
                    throw;
                }

    Should I alter this code? Given the documentation available for CRM, I'd expect the plugin to throw an InvalidPluginExecutionException like this:

                catch (FaultException<OrganizationServiceFault> e)
                {
                    localcontext.Trace(string.Format(CultureInfo.InvariantCulture, "Exception: {0}", e.ToString()));
                    
                    throw new InvalidPluginExecutionException("An error occurred in the plug-in.", e);
                }

    Also, I'm somewhat unsure if I need further exception handling in the methods that are invoked by the base plugin. For reference, here's what the base plugin does in its Execute method:


    try
                {
                    // Iterate over all of the expected registered events to ensure that the plugin
                    // has been invoked by an expected event
                    // For any given plug-in event at an instance in time, we would expect at most 1 result to match.
                    Action<LocalPluginContext> entityAction =
                        (from a in this.RegisteredEvents
                         where (
                         a.Item1 == localcontext.PluginExecutionContext.Stage &&
                         a.Item2 == localcontext.PluginExecutionContext.MessageName &&
                         (string.IsNullOrWhiteSpace(a.Item3) ? true : a.Item3 == localcontext.PluginExecutionContext.PrimaryEntityName)
                         )
                         select a.Item4).FirstOrDefault();
    
                    if (entityAction != null)
                    {
                        localcontext.Trace(string.Format(
                            CultureInfo.InvariantCulture,
                            "{0} is firing for Entity: {1}, Message: {2}",
                            this.ChildClassName,
                            localcontext.PluginExecutionContext.PrimaryEntityName,
                            localcontext.PluginExecutionContext.MessageName));
    
                        entityAction.Invoke(localcontext);
    
                        // now exit - if the derived plug-in has incorrectly registered overlapping event registrations,
                        // guard against multiple executions.
                        return;
                    }
                }
                catch (FaultException<OrganizationServiceFault> e)
                {
                    localcontext.Trace(string.Format(CultureInfo.InvariantCulture, "Exception: {0}", e.ToString()));
                    
                    // Handle the exception.
                    throw;
                }
                finally
                {
                    localcontext.Trace(string.Format(CultureInfo.InvariantCulture, "Exiting {0}.Execute()", this.ChildClassName));
                }


    Wednesday, January 22, 2014 8:36 AM

All replies

  • Hi Miguel,

    Personally, It's perfectly fine for BasePlugin handle exception like that. You don't need to change anything.

    When it comes to exception handling, you should stick to best practice article. It's enough for CRM plugin context.

    BTW, "FaultException<OrganizationServiceFault> e" is runtime exception so when it's occurred, let it throw, log it is enough.

    You only need to handle your business exception in your child class InternalExecute method.

    Hope it helps.

    Wednesday, January 22, 2014 8:55 AM
  • Thanks for the reply. The reason I asked is because this article mentions that "It is recommended that plug-ins only pass an InvalidPluginExecutionException back to the platform.". This seems to contradict what the base plugin does? Or should I just leave the base plugin for what it is, and just handle the FaulException in the InternalExecute method and throw an InvalidPluginExecutionException there?


    • Edited by Miguel_P Wednesday, January 22, 2014 9:05 AM
    Wednesday, January 22, 2014 9:04 AM
  • Hi Miguel,

    Yes, you're right. I just look back at my project and see that I use that code too.

    // Handle the exception.
    throw new InvalidPluginExecutionException(string.Concat(string.Format(Constants.PluginError, this.HandlerName), ex.Message, Environment.NewLine, ex.StackTrace));

    For user friendly, you can use your text to post back to user "An error occurred in the plug-in."

    So I guess we both agree on this points :-).


    • Edited by Linh Giang Wednesday, January 22, 2014 9:15 AM
    Wednesday, January 22, 2014 9:14 AM