ASP.NET Web API中的内容协商

时间:2014-05-19 20:16:12

标签: c# asp.net-web-api content-negotiation

我正在将一个Web服务迁移到ASP.NET Web Api 2,几乎在第一个障碍就遇到了麻烦。

我想这样做:

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

并且能够向服务询问“application / json”或“application / xml”(或者实际上任何其他可能的格式,例如Message Pack),并获得序列化响应。但它似乎只适用于JSON。

我已阅读this,并看到documentation明确指出框架无法处理匿名类型序列化为XML(严重)并且解决方案是不使用XML(严重)。

当我尝试调用它并请求XML作为响应类型时,我得到了

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

我没有删除对想要请求XML的客户的支持 - 但我真的无法找到解决方法 - 我该怎么办?

修改

我添加了这些:

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());

根据Dalorzo的回答,但没有任何区别。

为了澄清这一点,当我使用application/json的接受标头调用它时服务工作正常,但是当我使用application/xml的接受标头调用它时会发生炸弹。

4 个答案:

答案 0 :(得分:4)

您有3个选项:

  1. 创建一个具有正确名称的类,并返回该对象而不是匿名类型。
  2. 或者如果要返回匿名实例,则应删除XML格式化程序,因为匿名类型are not supported by XML Formatter

  3. 创建自己的格式化程序,继承自 MediaTypeFormatter BufferedMediaTypeFormatter

答案 1 :(得分:2)

您可以通过以下代码执行此操作:

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);
        }

答案 2 :(得分:0)

// 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
        )
    };
}  

答案 3 :(得分:0)

请在Chrome上浏览您的API路线。默认情况下,Chrome会以XML格式显示输出。如果没有发生这种情况,则意味着您的服务正在使用媒体格式阻止XML格式。

在这种情况下,您应该搜索WebApiConfig。如果没有任何内容,请将此文件添加到项目中

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);
            }
        }
    }
}

并在WebApiConfig.cs中添加:

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