【问题标题】:Upgrading to MVC4 RC: No MediaTypeFormatter is available to read an object of type 'TestRequestModel' from content with media type ''undefined''升级到 MVC4 RC:没有 MediaTypeFormatter 可用于从媒体类型为“未定义”的内容中读取类型为“TestRequestModel”的对象
【发布时间】:2012-06-07 14:41:27
【问题描述】:

我一直在使用 MVC4 测试版,目前正在努力升级到最近发布的 RC 版本。

模型绑定的复杂请求类型似乎发生了变化,但我无法弄清楚我做错了什么/做错了什么。

例如,假设我有以下 API 控制器:

public class HomeApiController : ApiController
{
    public TestModel Get()
    {
        return new TestModel
        {
            Id = int.MaxValue,
            Description = "TestDescription",
            Time = DateTime.Now
        };
    }
}

这会产生预期的结果:

<TestModel xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/xxxx">
    <Description>TestDescription</Description>
    <Id>2147483647</Id>
    <Time>2012-06-07T10:30:01.459147-04:00</Time>
</TestModel>

现在说我只是更改签名,接受请求类型,如下所示:

public TestModel Get(TestRequestModel request)
{
    ...

public class TestRequestModel
{
    public int? SomeParameter { get; set; }
}

我现在收到以下错误:

<Exception xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/System.Web.Http.Dispatcher">
    <ExceptionType>System.InvalidOperationException</ExceptionType>
    <Message>
        No MediaTypeFormatter is available to read an object of type 'TestRequestModel' from content with media type ''undefined''.
    </Message>
    <StackTrace>
    at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) at System.Web.Http.Controllers.HttpActionBinding.<>c__DisplayClass1.<ExecuteBindingAsync>b__0(HttpParameterBinding parameterBinder) at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() at System.Threading.Tasks.TaskHelpers.IterateImpl(IEnumerator`1 enumerator, CancellationToken cancellationToken)
    </StackTrace>
</Exception>

我查看了HttpContentExtensions 中引发此异常的源代码,但它看起来像是检查内容标题(我应该有),如果没有,它会尝试从MediaTypeFormatter 集合中为特定类型(它不能)获取格式化程序,然后抛出。

还有其他人经历过这种情况吗?我缺少一些全球注册?

【问题讨论】:

  • fiddler中的HTTP请求是什么?具体来说,Content-Type 标头值是什么?
  • 我可以手动传递application/jsonContent-Type,有趣的是,这让我克服了那个错误(我只在接受标头中传递了application/json)。但现在复杂类型以 null 的形式出现,这似乎有一些共同的潜在问题。
  • 那么accept 是什么? Accept: application/json 不起作用??尝试在参数上使用[FromBody]

标签: asp.net-mvc asp.net-mvc-4 asp.net-web-api model-binding


【解决方案1】:

我看到您的原始问题已得到解答,但要回答另一个问题,模型绑定在 RC 中有所改变。

http://weblogs.thinktecture.com/cweyer/2012/06/aspnet-web-api-changes-from-beta-to-rc.html

这个链接有一些关于它的细节。但总结一下似乎影响您的更改,模型绑定从请求的主体或 uri 中提取其值。对于以前的版本也是如此,但是对于候选版本,MVC4 默认情况下会在 body 中查找复杂类型,并在 uri 中查找值类型。

因此,如果您提交的请求中包含“SomeParameter”键的正文,您应该会看到它已绑定。或者,如果您将声明更改为:

 public TestModel Get(int? someParameter)
 {

 }

谢天谢地,团队预见到了这方面的潜在问题,并为我们留下了可以用来覆盖此行为的属性。

 public TestModel Get([FromUri]TestRequestModel request)
 {

 }

这里的关键是 [FromUri],它告诉模型绑定器在 uri 中查找值。还有[FromBody],如果你想把一个值类型放在请求体中。

【讨论】:

  • 感谢其他 RC 更改的链接。一段时间以来,我一直在寻找这样的综合清单。看起来我有很多属性要添加:)
【解决方案2】:

我们看到了同样的事情。在我们的例子中,问题是一个复杂的对象被传递到一个 get 方法中。我们需要在该方法的参数中添加一个 [FromUri] 属性。

http://forums.asp.net/t/1809925.aspx/1?GET+requests+with+complex+object+as+input+parameter

public class SearchController : ApiController
{
    // added [FromUri] in beta to RC transition otherwise media type formatter error
    public IQueryable<SearchResultEventModel> Get( [FromUri]SearchSpecModel search )
    {
        // ...
    }
}

【讨论】:

    猜你喜欢
    • 2018-05-29
    • 2012-09-12
    • 1970-01-01
    • 2016-06-29
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多