【问题标题】:Content Negotiation is not working in Web Api内容协商在 Web Api 中不起作用
【发布时间】:2025-12-27 03:40:12
【问题描述】:

我有以下代码来演示 web api 中的内容协商。但它会引发异常。

IEnumerable<Person> personList = _repository.GetAllPerson();

if (personList == null)
    throw new HttpResponseException(HttpStatusCode.NotFound);

IContentNegotiator negotiator = this.Configuration.Services.GetContentNegotiator();
ContentNegotiationResult result = negotiator.Negotiate(typeof(Person), this.Request, this.Configuration.Formatters);
if (result == null)
{
    var response = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
    throw new HttpResponseException(response);
}

HttpResponseMessage responseMsg = new HttpResponseMessage()
{                
    Content = new ObjectContent<IEnumerable<Person>>(
        personList, // What we are serializing 
        result.Formatter, // The media formatter
        result.MediaType.MediaType // The MIME type
        )
};

return Request.CreateResponse(HttpStatusCode.OK, responseMsg);

例外是:

“ObjectContent`1”类型未能序列化响应正文 内容类型'应用程序/json; charset=utf-8'。

请给我一个建议。我的 WebApiConfig.cs 代码是:

// Web API configuration and services

//XML output
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xml.UseXmlSerializer = true;

//Json output
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.UseDataContractJsonSerializer = true;
json.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
json.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All;

// Remove the XML formatter
//config.Formatters.Remove(config.Formatters.XmlFormatter);

// Web API routes
config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

【问题讨论】:

    标签: c# asp.net asp.net-web-api2


    【解决方案1】:

    这是关于序列化,而不是内容协商。我猜您正在查询数据库并使用实体框架从存储库中取回IQueryable 结果?尝试几个步骤:

    改变这个:

    json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All;
    

    到这里:

    json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Ignore;
    

    您可能还需要在 EF 配置中禁用延迟加载,具体取决于 Person 的形状:

    public MyEntitiesContext() : base("name=MyEntitiesContext", "MyEntitiesContext")
    {
        this.Configuration.LazyLoadingEnabled = false;
        this.Configuration.ProxyCreationEnabled = false;
    }
    

    另一种选择(对于非平凡的解决方案可能是更好的策略是从 Web api 返回不同的类(视图模型、dto 甚至投影),而不是返回您的 EF 实体。

    【讨论】:

      【解决方案2】:

      问题出在最后一行。

      return Request.CreateResponse(HttpStatusCode.OK, responseMsg);
      

      答案是:

      return new HttpResponseMessage()
                  {
                      Content = new ObjectContent<IList<PersonModel>>(
                          personModelList, // What we are serializing 
                          result.Formatter, // The media formatter
                          result.MediaType.MediaType // The MIME type
                          ),
                      StatusCode = HttpStatusCode.OK
                  };
      

      【讨论】: