Raw Message Processor

Topics: Web Api
Nov 1, 2010 at 2:11 AM

In case anyone else is trying to do this, I found a way of having an operation like this, with just a plain HttpResponseMessage return value:

 

[WebGet(UriTemplate = "Foo")]
        [OperationContract]
        public HttpResponseMessage GetFoo(HttpRequestMessage httpRequestMessage) {

            var response = new HttpResponseMessage();
            response.Content = HttpContent.Create("Hello World", "text/plain");
            return response;
        }

 

In order to do this I need a processor to map the return value of the operation into the HttpResponseMessage parameter of the pipeline.  I don't know if it is possible to actually replace the HttpResponseMessage that is provided by the pipeline, so I just copy the values over from the HttpResponseMessage that is returned from the operation.

    public class RawHttpProcessor : Processor {
        private HttpParameterDescription _ReturnValue;

        public RawHttpProcessor(HttpOperationDescription operation)  {
            _ReturnValue = operation.ReturnValue;
        }
        protected override IEnumerable<ProcessorArgument> OnGetInArguments() {

            var arguments = new List<ProcessorArgument>();
            arguments.Add(new ProcessorArgument(_ReturnValue.Name, _ReturnValue.ParameterType));
            arguments.Add(new ProcessorArgument(HttpPipelineFormatter.ArgumentHttpResponseMessage, typeof(HttpResponseMessage)));
            return arguments.ToArray();
        }

        protected override IEnumerable<ProcessorArgument> OnGetOutArguments() {
        
            return null;
        }

        protected override ProcessorResult OnExecute(object[] input) {
            var result = new ProcessorResult();
            var returnResponse = (HttpResponseMessage)input[0];
            var pipeLineResponse = (HttpResponseMessage) input[1];

            pipeLineResponse.Headers = returnResponse.Headers;
            pipeLineResponse.Content = returnResponse.Content;
            pipeLineResponse.StatusCode = returnResponse.StatusCode;
            
            return result;

        }
    }

In order to plug this processor in, you need to add this to your HostConfiguration class.
        public override void RegisterResponseProcessorsForOperation(HttpOperationDescription operation, IList<Processor> processors, MediaTypeProcessorMode mode) {
            processors.Clear();
            processors.Add(new RawHttpProcessor(operation));
        }

This is highly untested and experimental code, use at your own risk :-)

 

Coordinator
Nov 1, 2010 at 3:39 AM

Darrel

Rather than creating the response message, you could just pull in the response as well and make the method void. This way you are not replacing the entire response.

This works for example:

        [WebGet(UriTemplate="Foo/{id}")]
        public void GetFoo(HttpRequestMessage request, HttpResponseMessage response)
        {
            response.Content = HttpContent.Create("Foo");
        }

 

 

 

Nov 1, 2010 at 3:49 AM

Yes I could.  I just seem to have this compulsion to have a return value.  Not a big fan of out parameters I guess.  

I would never really use this RawProcessor in real code, I'm just trying to strip things down to the bare metal so I can grok what is going on and then build the magic layers back on top.  Also, it's good practice building a very simple processor :-)

Darrel

Coordinator
Nov 1, 2010 at 4:42 AM

It's not actually an out parameter in this case. We create the response message before hand and are just passing you a reference.

We started down the path of just returning a response, the downside was having to merge headers and such with the response that we create as you did in your code. :-)  As far as replacing the response message, in the current bits I don't think you can.

Agreed it is a good illustration of how you can intercept the response / add additional support that we did not provide in the box.

Thanks!

Glenn