3

I have an action in my web api that is returning a HttpResponseMessage:

public async Task<HttpResponseMessage> Create([FromBody] AType payload)
{
    if (payload == null)
    {
        throw new ArgumentNullException(nameof(payload));
    }

    await Task.Delay(1);

    var t = new T { Id = 0, Name = payload.tName, Guid = Guid.NewGuid() };

    var response = new MyResponse { T = t };

    var result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ObjectContent(typeof(MyResponse), response, new JsonMediaTypeFormatter { SerializerSettings = { NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore } }) };

    return result;
}

Now, my problem is that if a request is made and the request's Content-Type is application/xml, I should put the response's body using a xml formatter.

Is there a way to use a generic class and let the framework decide what formatter to use at runtime based on the request's content type?

Nkosi
  • 235,767
  • 35
  • 427
  • 472
Buda Gavril
  • 21,409
  • 40
  • 127
  • 196

2 Answers2

1

Use the CreateResponse extension method on the request and it will allow for content negotiation based on associated request. If you want to force the content type based on the content type of the request take it from the request and include it in the create response overloads.

public class MyApitController : ApiController {
    [HttpPost]
    public async Task<HttpResponseMessage> Create([FromBody] AType payload) {
        if (payload == null) {
            throw new ArgumentNullException(nameof(payload));
        }

        await Task.Delay(1);

        var t = new T { Id = 0, Name = payload.tName, Guid = Guid.NewGuid() };

        var response = new MyResponse { T = t };

        var contentType = Request.Content.Headers.ContentType;

        var result = Request.CreateResponse(HttpStatusCode.OK, response, contentType);

        return result;
    }

}

The type returned should ideally be based on what the request indicates it wants to accept. The framework does allow flexibility on that topic.

Check this for more info Content Negotiation in ASP.NET Web API

Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • I have done this and the request was an xml one and the response was json... I don't know why – Buda Gavril Nov 18 '16 at 13:51
  • Based on the accept header of the request. if you want to force the content based on the content type of the request take it from the request and include it in the create response overloads. `Request.CreateResponse(HttpStatusCode.OK, response, Request.Content.Headers.ContentType);` – Nkosi Nov 18 '16 at 13:52
  • With that the response content type will be based on the request content type. – Nkosi Nov 18 '16 at 13:58
0

An easier way to do this is to use the handy methods in Web API 2 ApiController.

[HttpPost]
public async Task<IHttpActionResult> Create([FromBody] AType payload)
{
    if (payload == null) 
    {
        return BadRequest("Must provide payload");
    }

    await Task.Delay(1);

    var t = new T { Id = 0, Name = payload.tName, Guid = Guid.NewGuid() };

    var response = new MyResponse { T = t };

    return Ok(response);
}
Dan Harms
  • 4,725
  • 2
  • 18
  • 28