How to go about catching controller activator exceptions in order to log them?

37 Views Asked by At

I have an asp.net framework 4.8 WebApi2 project and when I send a request to actions on a given controller I get a 500 error and the content shows it is due to a missing dependency. Quite correct, I've forgotten to configure one of my dependencies.

<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>An error occurred when trying to create a controller of type 'ValuesController'. Make sure that the controller has a parameterless public constructor.</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace> at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()</StackTrace>
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>Type 'ApiLab.WebApi.Controllers.ValuesController' does not have a default constructor</ExceptionMessage>
<ExceptionType>System.ArgumentException</ExceptionType>
<StackTrace> at System.Linq.Expressions.Expression.New(Type type) at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)</StackTrace>
</InnerException>
</Error>

For a little while I was calling the api from another application and the request was just disappearing with nothing showing up in my logs, for either application, which would've been very helpful in getting to the route of the problem sooner.

On the WebApi project I have an exception filter class UnhandledExceptionFilter : ExceptionFilterAttribute to log any unhandled exceptions. I have it registered globally like

HttpConfiguration config = GlobalConfiguration.Configuration;
config.Filters.Add(new UnhandledExceptionFilter());

and also, to cover all bases TestHandleErrorAttribute : HandleErrorAttribute registered using

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new TestHandleErrorAttribute());

It was my belief that, given that the controller DI would happen during the request pipeline then the unhandled exception would drop into one of those filters which I could then use to log it however that's not happening. I've tested throwing an exception from within an action on another controller and the UnhandledExceptionFilter worked as intended so I'm confident that that is working.

I'm guessing that either the dependency resolution happens outside of the context and thus doesn't end up being passed to one of the filters or it is happening within that context but something is swallowing it further up the chain.

So does anyone know what I need to be able to log that exception?

--- EDIT ---

Found clues to a "solution" at https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection#the-web-api-dependency-resolver

I'm using Autofac along with the ootb AutofacWebApiDependencyResolver however with a custom IDependencyResolver I can catch and log the Autofac.Core.DependencyResolutionException exceptions (which is the really useful bit).

Does anyone knows if there is a way to achieve a similar outcome without replacing AutofacWebApiDependencyResolver?

0

There are 0 best solutions below