Ctor of Message handlers

Topics: Web Api
Dec 1, 2011 at 11:23 AM

Hello

I've been asking myself how to chain the order of message handlers. For example for the following registration :

config.MessageHandlerFactory = () => container.GetExportedValues<DelegatingHandler>();

this doesn't work (not even invoked when request comes)

[ImportingConstructor]
		public AuthenticatingHandler(HttpMessageHandler innerHandler, IAuthenticationProvider authenticationProvider)
			: base(innerHandler)
		{
			_authenticationProvider = authenticationProvider;
		}

and this works

[ImportingConstructor]
public AuthenticatingHandler(IAuthenticationProvider authenticationProvider)
{
	_authenticationProvider = authenticationProvider;
}

I've been reading through the following topic : http://wcf.codeplex.com/discussions/254370. As I understand I should not  use the ctor with innerHandler if I'm not explicitly wiring a handlers on registration or with DI like  HttpMessageHandlerFactory here : https://gist.github.com/928823. Are there other considerations between the design ?

Thanks,

Thomas

 

Coordinator
Dec 3, 2011 at 4:50 AM

Hi Thomas

You shouldn't use the ctor that accepts a message handler if you are using IoC. Handlers expose an inner handler property. The message handler factory will automatically set the inner handler appropriately if you pass it existing handler instances. Thus you can return a collection of handlers and they will automatically get wired. The handlers themselves should provide a constructor that does not expect the inner handler as a constructor param. If you look at the ContactManager_Advanced example you will see that several handlers get wired up and each uses a constructor similar to your second example above i.e. it without an inner handler.

Hope this helps

Glenn

Dec 3, 2011 at 9:27 PM

Hi Glenn,

Thank you for your response. I though I could pass an inner handler in order to wire all the message handlers in order. I think this point is misleading in the API.

Otherwise, how could I wire my message handlers in order ? Let's say I have an Authentication message handler that should run at first and then a logging message handler that should run after. If I'm using IoC how can I guarantee the order of resolving instances ?

Thomas

Coordinator
Dec 3, 2011 at 9:58 PM

Thomas

Web API does the wiring for you. Just return the handlers in the order you want them wired and it will do it. In the past we only allowed you to wire via the ctor which made it difficult to work some IoC containers. You can search our discussion threads and will find a signficant amt of feedback in this regard.

So if you do this

config.MessageHandlers =()=>return new List<DelegatingHandler>{new Handler1(), new Handler2()} for example, then we will wire them up in the order they were return. If you check ContactManager_Advanced you will see that I use MEF to return handlers by doing a container.GetExportedValues<DelegatingHandler>(), which returns a collection of handlers.

Coordinator
Dec 3, 2011 at 10:02 PM

Thomas

The api of the handlers does allow you to wire handlers yourself as you can use handlers with HttpClient directly. On the server however we require to do it for you with you giving them to us in the order you want them wired. We discussed allow you to do both however it required us to walk the object graph then to validate that everything was wired up correctly which made the logic really complicated and had perf implications. So we decided to make things simple to just force you to give us the instances and we wire them up.

Coordinator
Dec 3, 2011 at 10:26 PM
Edited Dec 3, 2011 at 10:27 PM

"If I'm using IoC how can I guarantee the order of resolving instances?" 

That's a very good question and there's no one magic answer. In many cases order does not matter, though in some cases it definitely does. Here's a few ideas

  1. Being that the factory wires up instances, one possible way to do it would be to have the contract itself that you resolve from the container expose a member like Order that you could use for ordering.
  2. Many containers support the ability to specify order within metadata or config so you could use those facilities. Then when you resolve the collection it will automatically come back in the order you specified.
  3. Give each handler a specific contract like IMessageHandlerA, IMessageHandlerB. Then resolve each contract and put them in the order you want within the delegate that you pass for the factor
Dec 5, 2011 at 8:43 AM
gblock wrote:

So if you do this

config.MessageHandlers =()=>return new List<DelegatingHandler>{new Handler1(), new Handler2()} for example, then we will wire them up in the order they were return. If you check ContactManager_Advanced you will see that I use MEF to return handlers by doing a container.GetExportedValues<DelegatingHandler>(), which returns a collection of handlers.

 

I saw the sample, but does MEF guarantee the order of part resolution which is important in my case ?

gblock wrote:

Thomas

Web API does the wiring for you. Just return the handlers in the order you want them wired and it will do it. In the past we only allowed you to wire via the ctor which made it difficult to work some IoC containers. You can search our discussion threads and will find a signficant amt of feedback in this regard.

I think it's easier to wire up decorators in IoC tools than to guarantee the order of resolution.

Thanks,

Thomas

Dec 5, 2011 at 8:52 AM
gblock wrote:

"If I'm using IoC how can I guarantee the order of resolving instances?" 

That's a very good question and there's no one magic answer. In many cases order does not matter, though in some cases it definitely does. Here's a few ideas

  1. Being that the factory wires up instances, one possible way to do it would be to have the contract itself that you resolve from the container expose a member like Order that you could use for ordering.
  2. Many containers support the ability to specify order within metadata or config so you could use those facilities. Then when you resolve the collection it will automatically come back in the order you specified.
  3. Give each handler a specific contract like IMessageHandlerA, IMessageHandlerB. Then resolve each contract and put them in the order you want within the delegate that you pass for the factor


Thank you Glenn for all that help. I'll try to do something with metadata and keep you posted.

At the end I just wanted to say that I appreciate the way and commitement of you, and your team to help implementing web services with a new stack.

Thomas

Dec 6, 2011 at 7:29 AM

FYI, I return just an ordered collection of message handlers and all work like a charm. I was just mislead by the constructor arguments of message handler that I though I had to pass a innerHandler in. So returning an ordered collection works, I have just remember to return a collection sorted by descending order (the first message handler that should be called with "SendAsync" method should be the last in the collection.

Thanks,

Thomas

Mar 12, 2012 at 3:48 PM

Is there a way to access the MessageHandlerFactory from within MVC 4 webapi?  All I see is the MessageHandler object.

Mar 12, 2012 at 3:49 PM

The forums have moved for asp.net webapi

http://forums.asp.net/1246.aspx/1?Web+API