11

I'm trying to add a custom IHttpActionInvoker to my WebAPI application in order to prevent the need for lots of repeated exception handling code in my action methods.

There really doesn't seem to be much out there about how to do this other than this article. After writing my IHttpActionInvoker as per the article I added this code:

GlobalConfiguration.Configuration.Services.Remove(typeof(IHttpActionInvoker),
GlobalConfiguration.Configuration.Services.GetActionInvoker());

GlobalConfiguration.Configuration.Services.Add(typeof(IHttpActionInvoker),
new MyApiControllerActionInvoker());

Into a method within my Global.asax file. Now when executing a call to my API I get the following exception raised at the Remove() method:

The service type IHttpActionInvoker is not supported

I guess I have two questions.

  1. Considering there doesn't seen to be an awful lot out there about writing custom IHttpActionInvoker classes is this considered a good approach to solve exception handling in WebAPI applications?

  2. Does anyone know why I would get such an exception when executing the Remove() method and how best to fix this particular issue?

3 Answers 3

7

I suffered the same error you describe when attempting to remove the service.

I discovered I didn't need to remove anything from the global config, as it appears if you've registered the interface in your container then it will resolve this first.

For example, I'm using SimpleInjector and in my global.asax I have this:

container.Register<IHttpActionInvoker , MyApiControllerActionInvoker >();
// Register the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver =
   new SimpleInjectorWebApiDependencyResolver(container);

At runtime, it is resolving MyApiControllerActionInvoker dependency when required.

You can then perform exception handling in your customer ActionInvoker and any dependencies set in your constructor will be wired up correctly. The reason I was looking at the ActionInvoker was to get the constructor injection, since injecting into Attributes appears to require property injection.

Also rather than the remove/insert, replace seems to work. (in Global.asax)

GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionInvoker), new MyApiControllerActionInvoker(fooService));
Sign up to request clarification or add additional context in comments.

Comments

1

Have you considered registering an exception filter instead? Here's some documentation about that:

http://www.asp.net/web-api/overview/web-api-routing-and-actions/exception-handling

You shouldn't have to fall down to the action invoker layer if all you want to do is handle some exceptions in a particular way.

1 Comment

Many of the exceptions that developers want to capture are transformed into an HttpResponseException by Web API. This exception is swallowed long before exception filters are invoked, so a global exception filter isn't going to capture everything.
0

As for me it works with IActionInvoker instead of IHttpActionInvoker. As I understand, IHttpActionInvoker is used for the async api calls, isn't it?

public class RepControllerActionInvoker : ControllerActionInvoker
{
    ILogger _log;

    public RepControllerActionInvoker()
        : base()
    {
        _log = DependencyResolver.Current.GetService<ILogger>();
    }

    public override bool InvokeAction(ControllerContext controllerContext, string actionName)
    {
        try
        {
            return base.InvokeAction(controllerContext, actionName);
        }
        catch (Exception e)
        {
            _log.Error(e);
            throw new HttpException(500, "Internal error");
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.