Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Joey 20 posts 44 karma points
    Jan 03, 2012 @ 10:07
    Joey
    0

    Catching unhandled exceptions through /base framework

    I've been trying to catch unhandled exceptions in my services that I've exposed through "base" with no luck. All of the methods I've exposed work just fine but when I throw an exception myself on purpose or some code I have no control over throws an exception it never gets logged. I'm currently using NLog and I've already created a class that implements IErrorHandler which is properly installed on the service iteslef via an attribute. Bottom line is if I create a stand alone WCF Service I can catch unhandled exceptions with the afore mentioned class but with the service exposed through "base" it never logs anything and instead the compiler breaks on some umbraco httpmodule/handler class and gets transformed into an <error/> object.

    So the question is what is the proper way to catch and log unhandled exceptions server-side? What's the Umbraco equivelant of IErrorHandler?

     

    public class ServiceErrorHandler : IErrorHandler
    {
    private static Logger _logger = LogManager.GetCurrentClassLogger();

    /// <summary>
    /// Gets the logger.
    /// </summary>
    /// <value>The logger.</value>
    protected static Logger Logger
    {
    get
    {
    return _logger;
    }
    }

    // Provide a fault. The Message fault parameter can be replaced, or set to
    // null to suppress reporting a fault.

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
    FaultException fe = new FaultException(error.Message);

    fault = Message.CreateMessage(version, fe.CreateMessageFault(), "");
    }

    // HandleError. Log an error, then allow the error to be handled as usual.
    // Return true if the error is considered as already handled

    public bool HandleError(Exception error)
    {
    Logger.Fatal(error);
    return true;
    }
    }

    /// <summary>
    /// Installs a custom error handler for a WCF service
    /// </summary>
    public sealed class ErrorBehaviorAttribute : Attribute, IServiceBehavior
    {
    Type errorHandlerType;

    public ErrorBehaviorAttribute(Type errorHandlerType)
    {
    this.errorHandlerType = errorHandlerType;
    }

    public Type ErrorHandlerType
    {
    get { return this.errorHandlerType; }
    }

    void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
    {
    }

    void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
    {
    }

    void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
    {
    IErrorHandler errorHandler;

    try
    {
    errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
    }
    catch (MissingMethodException e)
    {
    throw new ArgumentException("The errorHandlerType specified in the ErrorBehaviorAttribute constructor must have a public empty constructor.", e);
    }
    catch (InvalidCastException e)
    {
    throw new ArgumentException("The errorHandlerType specified in the ErrorBehaviorAttribute constructor must implement System.ServiceModel.Dispatcher.IErrorHandler.", e);
    }

    foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
    {
    ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
    channelDispatcher.ErrorHandlers.Add(errorHandler);
    }
    }
    }

  • Tim 1193 posts 2675 karma points MVP 3x c-trib
    Jan 04, 2012 @ 15:23
    Tim
    0

    I think its not getting logged because /base doesn't use WCF services, so it doesn't run the IErrorHandler code (I think it has to be called using system.servicemodel for that to work). It might be worth having a look at code for /base in the source to double check (I'm not that up on its inner workings). From having a quick look though, /base just works as a http module intercepting requests and mapping them to the methods in your base config file, rather than being a "proper" web service.

    You might be able to hook into the errors on the module maybe (not sure how you'd do this though)? If the errors that are thrown by your code are of a specific type, you could check for them in a global error handler in Global.asax, and log them if they're found.

    Another option would be to log the errors in try catch blocks in your service code (although that's not very elegant).

    That said, if the code you have is a service already, do you need it to run with /base? Couldn't you just access your services directly?

Please Sign in or register to post replies

Write your reply to:

Draft