8

Я использую бета-версию MVC4 и в настоящее время работаю над обновлением до недавно выпущенного RC версия.Обновление до MVC4 RC: Нет MediaTypeFormatter доступен для чтения объекта типа TestRequestModel из содержимого с типом носителя '' undefined ''

Похоже, что сложные типы запросов привязки модели изменились, но я не могу понять, как/что я делаю неправильно.

Например, у меня есть следующий контроллер 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, которую он имеет для определенного типа (который он не может), а затем выбрасывает.

Кто-нибудь еще испытал это? Некоторая глобальная регистрация мне не хватает?

+0

Что такое HTTP-запрос в скрипаче?В частности, что такое значение заголовка «Content-Type»? – Aliostad

+0

Я могу вручную передать 'Content-Type'' application/json', что, интересно, заставляет меня пройти мимо этой ошибки (я пропускал 'application/json' только в заголовке accept). Но теперь сложные типы входят как null, что, по-видимому, имеет общую общую проблему. –

+0

Итак, что же вы тогда «принимаете»? 'Accept: application/json' не работает? Попробуйте использовать '[FromBody]' для параметра. – Aliostad

ответ

13

Я вижу, ваш первоначальный вопрос был дан ответ, но ответить на другую, модель связывания несколько изменилась в РЦ.

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

Эта ссылка имеет некоторые подробности о нем. Но суммируя изменения, которые, как представляется, влияют на вас, привязка модели тянет ее значения либо из тела, либо из uri запроса. Это справедливо и для предыдущих выпусков, но с кандидатом на выпуск MVC4 по умолчанию будет искать тело для сложных типов и uri для типов значений.

Итак, если вы отправляете тело с запросом, содержащим ключ «SomeParameter», вы должны увидеть его привязку. Или вы могли бы связать с URL, если изменить декларацию:

public TestModel Get(int? someParameter) 
{ 

} 

К счастью, команда предвидит возможные проблемы с этим и оставили нас с атрибутами, мы могли бы использовать, чтобы переопределить это поведение.

public TestModel Get([FromUri]TestRequestModel request) 
{ 

} 

Ключевым моментом здесь является [FromUri], который говорит модель связующего, чтобы посмотреть в Ури для значений. Существует также [FromBody], если вы хотите поместить тип значения в тело запроса.

+0

Спасибо за ссылку на другие изменения 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) 
    { 
     // ... 
    } 
} 
Смежные вопросы