Is it possible to change MediaTypeFormatter to JSON for only one class?

I have a web api where the global configuration is configured to use: XmlMediaTypeFormatter

My problem is that I want to extend this web api with a new controller that uses JsonMediaTypeFormatter instead.

Is it possible to change MediaTypeFormatter to JSON for only one API controller class?

My problem is not returning JSON, I added this with returning HttpResponseMessage:

return new HttpResponseMessage { Content = new ObjectContent<string>("Hello world", new JsonMediaTypeFormatter()), StatusCode = HttpStatusCode.OK }; 

Upon request, I get this 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 VMRegistrant as an argument:

 public HttpResponseMessage CreateRegistrant(VMRegistrant registrant) { // Save registrant in db... } 

But the problem is when I call the action with JSON, it fails.

+7
source share
3 answers

You can force your controller to return IHttpActionResult and use the HttpRequestMessageExtensions.CreateResponse<T> extension method 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 independently read and deserialize the content from the Request object by 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); } 
+4
source

Yes, it is possible to change MediaTypeFormatters only one class / controller. If you want to save and restore the default formatter, you can do the following:

  • At the beginning of the request, the old formats are saved
  • Clear Formatter Collection
  • Add the desired formatter
  • At the end of the request, copy the old formats

I think this is easy to do with 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 use:

 [ChangeFormatterAttribute(typeof(JsonMediaTypeFormatter))] public class HomeController : ApiController { public string Get() { return "ok"; } } // ... [ChangeFormatterAttribute(typeof(XmlMediaTypeFormatter))] public class ValuesController : ApiController { public string Get() { return "ok"; } } 
+1
source

Perhaps you may have a formatter of your media type that accepts only the type that your controller handles:

 public class Dog { public string Name { get; set; } } public class DogMediaTypeFormatter : JsonMediaTypeFormatter { public override bool CanReadType(Type type) { return type == typeof (Dog); } } 

This may not be the best solution: I

0
source

All Articles