What's the best approaches in passing the data between operation handlers and formatters

Topics: Web Api
Dec 1, 2011 at 10:57 AM


It's a follow-up to the previous topic here : http://wcf.codeplex.com/discussions/281055

The make long story short, my problem was to return a status code from a formatter. In fact I have to access an external server from the formatter to read a gif and write it to the stream. If there is the problem while accessing external server (network connection fails, etc.), I cannot set a status code (503 for example) because as we're about to write to the response stream it's too late. So we have a 500 error ResponseRead failed.

As suggested in the previous topic, I could first read my gif in operation handler and set the status code if it fails, or cache the gif with HttpClient and underlying WinInet and in the formatter retrieve the gif from the cache. (the cache doesn't work for me for the moment).

The second solution would be a possibility to pass the data from operation handler to formatter, but actually it's not possible as in the formatter we can only access the header values (I won't put the binary representation in the header value). I know that it's such an extreme case but don't you think that we should have a possibility to do that for other cases ? What would be other techniques as workaround for my issue ?



Dec 1, 2011 at 11:26 PM

The image should be the content of the response, right? I would think that you would produce the image object as the output parameter from your operation handler so that it get passed to the formatter directly.

Daniel Roth

Dec 1, 2011 at 11:27 PM
Edited Dec 1, 2011 at 11:29 PM

Formatters can be created through dependency injection. That means you could inject an image service in the constructor of the formatter that provides access to the image. You don't want to rely on threading for this, but you could possibly put a state key (guid) in the content headers and then pass that key to the service to get the data it needs. You could clean out the service when the request dies so that it doesn't hold on to the state. You should use a key rather than relying on thread local storage. Formatters are not scoped to a request, so the collection backing the image service would need to thread safe as it will be accessed by multiple callers.

To be fair, I have not tried this, but in the white board of my brain it's possible. I have done similar things before which is what leads me in this direciton. :-)

Dec 1, 2011 at 11:56 PM

Dan, if the handler is returning the content, then it will also have to perform conneg if the resource is supporting different media types. And in that case there's no point in using a formatter.

Dec 2, 2011 at 6:55 AM

Hi Glen, I'm interested in your assertion "Formatters can be created through dependency injection". I didn't see any "FormattersFactory" as per Messages and Operations.

Only way i found to add / create a Formatter is Formatters.Add(new MyFormatter()); within WebApiConfiguration.

Unless using a ServiceLocator approach, I don't see how to have the formatter created by my IoC.

Do you have any example for Formatters + DI/IoC?

Dec 2, 2011 at 7:51 AM


It's no problem with formatters creation. Though, I'm interested about crixo72 question.

The problem is that I have to access an external server from the formatter to get the presentation and if there is a problem it's to late to set the appropriate status code error. I can access it in operation handler and cache it, or set the status code error if not possible. If all is ok, the formatter can retrieve it from the cache and process the representation. But I don't like to rely on cache for this purpose. I would prefer to pass what's needed from operation handler to the formatter, set some sort of context, as I don't want to tamper the content in operation handler because as you said there's no need for the formatter anymore.


Dec 2, 2011 at 7:20 PM
Edited Dec 2, 2011 at 7:23 PM

@crixo72, what I mean is you can use a dependency injection container to create your formatters. Instead of adding a  new instance, you resolve from the IoC. There's an AddRange extension method you can use on Formatters to pass in the collection.

@tajskula, let em explain as it has a few complexities. Disclaimer: These hoops being proposed are only necessary if you are returning a T from your service which is not an image and where you want to just represent T differently AND where you need error handling.

1. The service I am talking about is not a web service, it's a service in the DI sense. An operation handler (or ideally a message handler since it is async) would do the work of downloading the image, and if the image failed throw an HttpResponseException. That handler would get injected with this shared image service we are talking about say IImageService. IImageService would expose a method like SetValue with a key. In this case the handler would create a new guid probably for the key and pass the image object as the value. The content headers would then get set with the key. The formatter then use that key with the image service to get the image. You need to do the whole key thing because of the fact that the formatter is shared and because you can't rely on TLS or OperationContext within a formatter.

2. An alternative is to just have a separate operation for returning the image which has a different uri template, say "/image". The operation just returns HttpContent which contains an image. Then there's no formatter or handler to worry about. It's much less hassle, but does require the second operation. If you wanted to be clever you could go further and use a message handler to rewrite requests to that resource that contain an accept header of "image/png" to have the "/image" on the end. This is basically the reverse of the uri extension handler in the ContactManager sample.

Dec 5, 2011 at 7:35 AM


Thank you for your help. I think the first approach is better. I'll try this.