简体   繁体   中英

Content Negotiation in ASP.NET Web API

I'm migrating a web service to ASP.NET Web Api 2, and hitting trouble at almost the first hurdle.

I want to do this:

public class SomeController : ApiController
{
    [Route("some\url")]
    public object Get()
    {
        return { Message = "Hello" };
    }
}

And be able to ask the service for either "application/json" or "application/xml" (or indeed any other potential format, such as Message Pack), and get a serialized response. But it seems it only works for JSON.

I've read this and seen the documentation which states clearly that the framework cannot handle serialization of anonymous types into XML (seriously) and that the solution is to not use XML (seriously).

When I attempt to call this and request XML as response type, I get

The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.

I'm not removing support for clients wanting to ask for XML - but I genuinely can't find a work around for this - what can I do?

Edit

I've added these:

System.Web.Http.GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
config.Formatters.Insert(0, new System.Net.Http.Formatting.JsonMediaTypeFormatter());
config.Formatters.Insert(0, new System.Net.Http.Formatting.XmlMediaTypeFormatter());

as per Dalorzo's answer, but it made no difference.

For clarification, the service works absolutely fine when I call it using an accept header of application/json , but bombs when I call it with an accept header of application/xml .

You have 3 options:

  1. Create a class with a proper name and return the object instead of an anonymous type.
  2. Or if you want to return the anonymous instance, you should remove XML formatter, because anonymous types are not supported by XML Formatter

  3. Create your own formatter inheriting from MediaTypeFormatter or BufferedMediaTypeFormatter

You can do it by following code :

public HttpResponseMessage GetTestData()
        {        
               var testdata = (from u in context.TestRepository.Get().ToList()                            
                            select
                                 new Message
                                 {
                                     msgText = u.msgText                                    
                                 });    
                return ActionContext.Request.CreateResponse(HttpStatusCode.OK, testdata);
        }
// This Code Is Used To Change Contents In Api
public HttpResponseMessage GetAllcarDetails( string formate)
{
    CarModel ST = new CarModel();
    CarModel ST1 = new CarModel();
    List<CarModel> li = new List<CarModel>();

    ST.CarName = "Maruti Waganor";
    ST.CarPrice = 400000;
    ST.CarModeles = "VXI";
    ST.CarColor = "Brown";

    ST1.CarName = "Maruti Swift";
    ST1.CarPrice = 500000;
    ST1.CarModeles = "VXI";
    ST1.CarColor = "RED";

    li.Add(ST);
    li.Add(ST1);
    // return li;

    this.Request.Headers.Accept.Add(
      new MediaTypeWithQualityHeaderValue("application/xml"));
      //For Json Use "application/json"

    IContentNegotiator negotiator =
        this.Configuration.Services.GetContentNegotiator();

    ContentNegotiationResult result = negotiator.Negotiate(
        typeof(List<CarModel>), this.Request, this.Configuration.Formatters);

    if (result == null) {
        var response = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
        throw new HttpResponseException(response);
    }

    return new HttpResponseMessage() {
        Content = new ObjectContent<List<CarModel>>(
            li,             // What we are serializing 
            result.Formatter,           // The media formatter
            result.MediaType.MediaType  // The MIME type
        )
    };
}  

Please browse your API route on Chrome. Chrome, by default shows output in XML format. If that doesn't happen, it means that your service is preventing XML format using media formatting.

And in that case, you should search your WebApiConfig. If nothing is present there, add this file to your project

using System.Net.Http.Formatting;
using System.Collections.Generic;
using System.Net.Http;
using System;
using System.Linq;
using System.Net.Http.Headers;
namespace ExampleApp.Infrastructure
{
    public class CustomNegotiator : DefaultContentNegotiator
    {
        public override ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
        {
            if(request.Headers.UserAgent.Where(x=>x.Product!=null&& x.Product.Name.ToLower().Equals("chrome")).Count() > 0)
            {
                return new ContentNegotiationResult(new JsonMediaTypeFormatter(), new MediaTypeHeaderValue("application/xml"));
            }
            else
            {
                return base.Negotiate(type, request, formatters);
            }
        }
    }
}

and, in WebApiConfig.cs , add:

config.Services.Replace(typeof(IContentNegotiator), new CustomNegotiator());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM