19

Closed

Per-Route Message Handler

description

Message handlers are the extensibility points to implement authentication. But they are also global only.

In more complex scenarios you have different authentication needs for different services (in a single app - for e.g. multi-tenancy). This is currently not possible.

It would be good to have more scope options for message handlers, e.g. per route.

(Action filters are not suitable for authentication, because of ordering issues)
Closed Jul 18, 2012 at 8:16 PM by DRavva
Verified working of this feature.

comments

BradWilson wrote May 2, 2012 at 3:13 AM

The implementation of this feature will allow users to specify the "final" message handler in the request chain for a given route. By default today, that final handler is HttpControllerDispatcher. This will enable two scenarios:
  1. The original feature request, which is to be able to add message handlers on a per-route basis;
  2. Allow "ride-along" frameworks to use routing to dispatch to their own (non-IHttpController) endpoints.
What this means in practical terms is that, if you want to provide one or more message handlers on a per-route basis, those message handlers will have to run after routing has run (so, basically last), and if you want to preserve the dispatching to controllers, your final handler must delegate to HttpControllerDispatcher.

There will be no new overloads for MapHttpRoute planned, but the developer could write their own as needed, using HttpRouteCollection.CreateRoute to create their route with the handler that they want to use for dispatching.

DominickBaier wrote May 2, 2012 at 6:21 AM

yay ;)

BradWilson wrote May 3, 2012 at 3:12 PM

Checked in with snapshot f59892797e46d31004c11ac4e9e4ee060282187f.

davebettin wrote May 3, 2012 at 5:07 PM

This is great. No, great great.

I do have one question. In the web host scenario, is it still not possible to replace the default handler or even the controller dispatcher? It looks to be stamped into the GlobalConfiguration.

Could you pull the routing dispatcher from the dependency resolver?

It would be nice to take advantage of all the work in the web host, but still have the ability to create your own dispatching behavior (i.e, "ride-along" frameworks) or even your routing dispatcher (e.g, lightweight proxies).

I don't see a way to extend or replace these handlers without resorting to reflection hacks or creating your own web host.

BradWilson wrote May 3, 2012 at 7:22 PM

There is no way to replace HttpRoutingHandler, by design.

There is no way to replace HttpControllerDispatcher as the default, though you can obviously replace it on a per-route basis, which was the point of this feature. :) The reality is that there is very little actual logic in this class now. It does:
  1. Calls IHttpControllerSelector.SelectController(), which returns a controller descriptor,
  2. Returns 404 if the selector returns a null descriptor.
  3. Calls descriptor.CreateController(), which creates the controller by way of IHttpControllerActivator and returns an IHttpController.
  4. Returns 404 if the descriptor returns a null controller.
  5. Calls controller.ExecuteAsync()
You'll get a lot more mileage out of replacing one of more of these other services (for example, replacing IHttpControllerSelector if you want to change the selection logic; replacing IHttpControllerActivator to change the controller construction strategy, etc.).

davebettin wrote May 3, 2012 at 10:29 PM

Thanks for the follow-up. That all makes sense.

Looking more at the code, we can take advantage of the routing extensibility points via the HttpCollectionRoute.Add method.