我一直在使用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
集合中获取格式化程序(它不能),然后抛出。
还有其他人经历过吗? 我缺少一些全球注册?
我看到您最初的问题已得到解答,但要回答另一个问题,RC 中的模型绑定发生了一些变化。
http://weblogs.thinktecture.com/cweyer/2012/06/aspnet-web-api-changes-from-beta-to-rc.html
此链接包含有关它的一些详细信息。但是,为了总结似乎影响你的更改,模型绑定从请求的正文或 uri 中提取其值。对于以前的版本也是如此,但对于候选版本,默认情况下,MVC4 将查找正文中的复杂类型,以及值类型的 uri。
因此,如果您提交包含"SomeParameter"键的请求的正文,您应该会看到它已绑定。或者,如果将声明更改为:
public TestModel Get(int? someParameter)
{
}
值得庆幸的是,团队预见到了这一点的潜在问题,并为我们留下了可以用来覆盖此行为的属性。
public TestModel Get([FromUri]TestRequestModel request)
{
}
此处的关键是[FromUri]
,它告诉模型绑定程序在 uri 中查找值。如果要在请求正文中放置值类型,还有[FromBody]
。
我们看到同样的事情。在我们的例子中,问题是一个复杂的对象被传递到一个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 )
{
// ...
}
}