I have a web api, where the global configuration is configured to use: XmlMediaTypeFormatter
My problem is I wont to extend this web api with a new controller, that uses the JsonMediaTypeFormatter instead.
Is it possible to change the MediaTypeFormatter to JSON for only one API Controller class?
My problem is not returning JSON, I have accumplished this with returning HttpResponseMessage:
return new HttpResponseMessage
{
Content = new ObjectContent<string>("Hello world", new JsonMediaTypeFormatter()),
StatusCode = HttpStatusCode.OK
};
It's on the request I get the problem. If I have an object with two properties:
public class VMRegistrant
{
public int MerchantId { get; set; }
public string Email { get; set; }
}
And my controller action takes the VMRegistrant as argument:
public HttpResponseMessage CreateRegistrant(VMRegistrant registrant)
{
// Save registrant in db...
}
But the problem is when I call the action with JSON it fails.
Yes, it's possible to change the MediaTypeFormatters
for only one class/controller. If you want to save and restore the default formatters you can follow these steps:
I think this is easily done by an ActionFilterAttribute
:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class ChangeFormatterAttribute : ActionFilterAttribute
{
private IEnumerable<MediaTypeFormatter> oldFormatters;
private MediaTypeFormatter desiredFormatter;
public ChangeFormatterAttribute(Type formatterType)
{
this.desiredFormatter = Activator.CreateInstance(formatterType) as MediaTypeFormatter;
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
var formatters = actionContext.ControllerContext.Configuration.Formatters;
oldFormatters = formatters.ToList();
formatters.Clear();
formatters.Add(desiredFormatter);
base.OnActionExecuting(actionContext);
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
var formatters = actionExecutedContext.ActionContext.ControllerContext.Configuration.Formatters;
formatters.Clear();
formatters.AddRange(oldFormatters);
base.OnActionExecuted(actionExecutedContext);
}
}
And the usage:
[ChangeFormatterAttribute(typeof(JsonMediaTypeFormatter))]
public class HomeController : ApiController
{
public string Get()
{
return "ok";
}
}
// ...
[ChangeFormatterAttribute(typeof(XmlMediaTypeFormatter))]
public class ValuesController : ApiController
{
public string Get()
{
return "ok";
}
}
You can have your controller return an IHttpActionResult
and use the extension method HttpRequestMessageExtensions.CreateResponse<T>
and specify the formatter you want to use:
public IHttpActionResult Foo()
{
var bar = new Bar { Message = "Hello" };
return Request.CreateResponse(HttpStatusCode.OK, bar, new MediaTypeHeaderValue("application/json"));
}
Another possibility is to use the ApiController.Content
method:
public IHttpActionResult Foo()
{
var bar = new Bar { Message = "Hello" };
return Content(HttpStatusCode.OK, bar, new JsonMediaTypeFormatter(), new MediaTypeHeaderValue("application/json"));
}
Edit:
One possibility is to read and deserialize the content yourself from the Request
object via reading from the stream and using a JSON parser such as Json.NET to create the object from JSON:
public async Task<IHttpActionResult> FooAsync()
{
var json = await Request.Content.ReadAsStringAsync();
var content = JsonConvert.DeserializeObject<VMRegistrant>(json);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With