Question

Using the WCF Web API how would I go about changing a response's content body after the application logic has been run but before it's returned to the user. The goal is if suppressstatuscontent is true we:

  • Add a statuscode field to the content body
  • Change the statuscode on the response to 200

I have overridden a DelegatingChannel and in the SendAsnyc have some code that looks like this:

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
                   {
                    return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>(task =>
                    {
                        var response = task.Result;

                         if (CheckIfRequestHadSuppressStatusCode(request) == true)
                         {
                             string newResponse = (response.Content == null) ? "" : response.Content.ReadAsString();
                             newResponse = "<body>" +newResponse + "</body><statuscode>" + response.StatusCode + "</statuscode>";
                             response.StatusCode = HttpStatusCode.OK;                                 
                         }

                        return response;
                    });

A major problem is this doesn't handle BOTH xml and Json. I feel like there must be a much better way to go about the problem as this feels very hacky.

Was it helpful?

Solution

I'm not sure of the right approach but I would try something like this,

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
      {
        return base.SendAsync(request, cancellationToken)
            .ContinueWith<HttpResponseMessage>(task =>
               {
                var response = task.Result;

                if (CheckIfRequestHadSuppressStatusCode(request) == true)
                  {
                   switch(response.Content.Headers.ContentType.MediaType) {
                     case "application/xml":
                        response.Content = new XmlWithStatusContent(response.Content)
                        break;
                     case "application/json":
                        response.Content = new JsonWithStatusContent(response.Content)
                        break;
                  }

                  response.StatusCode = HttpStatusCode.OK;                                 
                }

        return response; });

You can encapsulate the code that adds the extra status code markup in specialized versions of HttpContent (e.g. XmlWithStatusContent and JsonWithStatusContent).

OTHER TIPS

You could parse the content as either XML or JSON (you can encapsulate that functionality in it's own class) which then gives you the ability to add the field independent of the format (independent in the sense that the SendAsync doesn't need to know).

var newResponse = ContentDecoder.Parse(response.Content).AddField("statuscode", response.StatusCode).ToString();

assuming Parse would return come kind of content object you can modify without having to know what the format is.

It's not a really a nice solution but it encapsulates the hackiness away a bit.

Update: Assuming you can dereive from HttpResponseMessage and are in full control of generating the response then you could have specialised subclasses dealing with it:

interface IHttpResponseContent
{
    void AddField(string name, string value);
}

class XmlHttpResponseMessage : HttpResponseMessage, IHttpResponseContent
{
}

When generating the response you create Xml/JsonHttpResponseMessage objects instead. Then you can do:

var newResponse = response as IHttpResponseContent;
if (newResponse != null)
{
    newResponse.AddField("statuscode", response.StatusCode);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top