【问题标题】:No MediaTypeFormatter is available to read an object of type 'Advertisement' in asp.net web api没有 MediaTypeFormatter 可用于在 asp.net web api 中读取“广告”类型的对象
【发布时间】:2015-08-13 04:07:34
【问题描述】:

我有一个名为广告的课程:

 public class Advertisement
{
    public string Title { get; set; }
    public string Desc { get; set; }
}

在我的控制器中:

public class OrderController : ApiController
{
    public UserManager<IdentityUser> UserManager { get; private set; }

    // Post api/Order/Test

    [Route("Test")]
    public IHttpActionResult Test(Advertisement advertisement)
    {
        var currentUser = User.Identity.GetUserId();
        Task<IdentityUser> user = UserManager.FindByIdAsync(currentUser);

      return Ok(User.Identity.GetUserId());
    }

但是当我用 Postman 测试它时,我遇到了这个错误,

 "Message": "The request contains an entity body but no Content-Type header. The inferred media type 'application/octet-stream' is not supported for this resource.",
"ExceptionMessage": "No MediaTypeFormatter is available to read an object of type 'Advertisement' from content with media type 'application/octet-stream'.",
"ExceptionType": "System.Net.Http.UnsupportedMediaTypeException",
"StackTrace": "   at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)\r\n   at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)"

AnyBody 可以帮助我吗?

【问题讨论】:

  • 从我看来你没有 Content-Type 标头的错误?在您的 Postman 调用中添加适当的标头 Content-Type ,这应该可以解决它。
  • 我的标题中有Content-TypeAccept @DaveAgaba
  • 在下面查看我的答案。

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


【解决方案1】:

"ExceptionMessage": "没有 MediaTypeFormatter 可用于从媒体类型为 'application/octet-stream' 的内容中读取类型为 'Advertisement' 的对象。",

这意味着您的应用程序无法读取 octet-stream Content-Type - 这是请求提供的内容。这是我对 Web API 的一种挫败感。但是有一种方法可以解决它。简单的方法是将 Content-type 修改为易于阅读的“application/json”或“application/xml”。 更难的方法是提供您自己的 MediaTypeFormatter。

【讨论】:

  • “this”教程链接现已失效。
【解决方案2】:

在你的WebApiConfig.cs 中添加这个寄存器

config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/octet-stream"));

【讨论】:

  • 这不起作用。 config.Formatters.JsonFormatter.CanWriteType(typeof(MyModel));返回 false。
  • 尽管这个答案是解决这个问题的最佳答案,但修改一个有效的 WebAPI 并不是我希望解决问题的方法。我确信 Postman 可以设置为发送正确的数据,而不是仅仅因为您需要测试并且无法构建正确的解决方案而修改服务器以接收意外的数据类型。简而言之,我想测试我将从客户那里收到什么,而不是不同的方法。
  • 在尝试发布 multipart/form-data 时遇到了与 OP 类似的情况。我尝试添加这一行并将application/octet-stream 换成multipart/form-data。应该有效,但它没有 - 仍然再次出现与 OP 相同的 500 错误,只是我的引用 multipart/form-data
【解决方案3】:

几个问题:

  1. 不要将其发布为application/octet-stream,而是使用application/json;charset=UTF-8
  2. public IHttpActionResult Test(Advertisement advertisement) 里面需要有[FromBody]

    public IHttpActionResult Test([FromBody]Advertisement advertisement) { ... }

    默认情况下,ApiController 期望传入的任何内容都代表 URL 参数,因此您需要 [FromBody] 来处理您在请求正文中发布的任何想要解析的数据。

  3. 你需要用[System.Web.Http.HttpPost] 装饰你的Post 方法,这样它就不会认为它是MVC 版本[System.Web.Mvc.HttpPost]。确保你放了完整的东西,因为[HttpPost] 也将默认为 MVC 版本。将Test 重命名为Post 也可能不是一个坏主意,尽管您可能将其用于单元测试方法,因此不确定。

  4. 以 JSON 格式发送您的数据:{ Title: "some title", Desc: "some description" }

  5. Post() 函数中使用 advertisement 做一些事情:

    string title = advertisement.Title; string desc = advertisement.Desc;

【讨论】:

  • “默认情况下,ApiController 期望传入的任何内容来表示 URL 参数”...我不相信这是真的,这也不是我使用它的经验。请参阅docs.microsoft.com/en-us/aspnet/web-api/overview/…,其中说 “默认情况下,Web API 使用以下规则绑定参数: ....对于复杂类型,Web API 尝试从消息正文中读取值”跨度>
  • @ADyson 除非您不指定该标签,否则没有什么可以告诉它从正文中读取。如果你不让它知道期望有一个“复杂类型”,它就不知道它在那里。相信我。尝试在没有[FromBody] 标签的情况下运行它,看看在你批评之前你能走多远。尽管任何文档可能会说什么,但知识的实际应用是无法替代的。不管你信不信,即使是微软有时也会出错。 MS 在他们的网站上有一个多部分 POST 的示例,该示例甚至无法正常工作。
  • “如果你不让它知道期望有一个“复杂类型”“......对不起,你是什么意思?复杂类型是不是简单类型之一的任何类型的对象,例如int、string 等。因此,如果您将Advertisement advertisement(根据问题中的示例)作为参数在操作方法中,那么根据定义模型绑定器将知道它,并且由于它不是定义的简单类型之一,它一定是一个复杂的。所以默认情况下它会尝试从正文中读取它,除非您另有说明。我有很多工作示例(使用 Web API 2 / .NET 4.6)。
  • @ADyson 您可能有一点需要进行更多研究:tutorialsteacher.com/webapi/parameter-binding-in-web-api - 它证实了您所说的,默认行为 is 应该抓取一个复杂的 obj(例如默认情况下来自正文的advertisement) 和来自 URL 参数的简单参数,不需要标签。我有一个 JSON 对象,我已将其字符串化并发布,试图对其进行模型绑定,但发现没有[FromBody],它将为空。很确定我使用的是 .NET 4.5.2,但我查看了 Core,它似乎需要标签:andrewlock.net/model-binding-json-posts-in-asp-net-core
  • 我也使用application/json 作为我的内容类型,而不是推荐的application/x-www-form-urlencoded,所以这可能起到了作用。是的,我假设他正在做一个帖子。正如您所说,如果它是 GET,他的错误将没有任何意义。但即便如此,他也需要一个[HttpGet] 标签。至于不使用输入对象并将其放入我的答案中,这样做是否彻底。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-19
  • 1970-01-01
  • 2018-05-29
  • 2012-09-12
  • 1970-01-01
  • 2016-06-29
相关资源
最近更新 更多