8

Utilizzo la MVC4 beta e sto attualmente lavorando per l'aggiornamento alla RC rilasciata di recente versione.Aggiornamento a MVC4 RC: No MediaTypeFormatter è disponibile per leggere un oggetto di tipo 'TestRequestModel' dal contenuto con tipo di supporto '' indefinito ''

Sembra che i tipi di richieste complesse modello vincolante è cambiato, ma io non riesco a capire come/cosa sto facendo male.

Per esempio, dire che ho il seguente controller API:

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

Questo produce il risultato previsto:

<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> 

Ora dicono mi limito a cambiare la firma, prendendo in un tipo di richiesta, come questo:

public TestModel Get(TestRequestModel request) 
{ 
    ... 

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

ora ottengo il seguente errore:

0.123.516,41 mila
<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> 

Ho guardato il codice sorgente di dove questo viene generata un'eccezione nel HttpContentExtensions, ma sembra che verifica la presenza di intestazioni di contenuto (che dovrei avere), e se non ha che cerca per ottenere un formattatore dalla raccolta MediaTypeFormatter che ha per il tipo specifico (che non può) e quindi genera.

Chiunque altro ha provato questo? Qualche registrazione globale mi manca?

+0

Qual è la richiesta HTTP nel violinista?In particolare qual è il valore dell'intestazione 'Content-Type'? – Aliostad

+0

Posso passare manualmente un 'Content-Type' di' application/json', che, curiosamente, mi supera l'errore (avevo passato 'application/json' solo nell'intestazione accept). Ma ora i tipi complessi arrivano come nulli, il che sembra condividere alcuni problemi di fondo comuni. –

+0

Allora, che cosa c'è in te? Accetto? 'Accettare: application/json' non funziona ?? Prova a usare '[FromBody]' sul parametro. – Aliostad

risposta

13

vedo la tua domanda iniziale è stato risposto, ma per rispondere l'altro, legame modello è cambiato un po 'in RC.

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

Questo legame ha alcuni dettagli su di esso. Ma per riassumere il cambiamento che sembra influire su di te, il binding del modello estrae i suoi valori dal corpo o dall'ur della richiesta. Questo vale anche per le versioni precedenti, ma con la release candidate, MVC4, per impostazione predefinita, cercherà il corpo per i tipi complessi e l'uri per i tipi di valore.

Quindi, se si invia un corpo con la richiesta contenente la chiave "SomeParameter", è necessario visualizzarlo. Oppure si potrebbe legarsi con l'url se si cambia la dichiarazione:

public TestModel Get(int? someParameter) 
{ 

} 

Per fortuna, la squadra prevedeva i potenziali problemi con questo e ci ha lasciato con gli attributi che potremmo usare per ignorare questo comportamento.

public TestModel Get([FromUri]TestRequestModel request) 
{ 

} 

La chiave qui è la [FromUri] che racconta il modello legante di guardare in uri per i valori. C'è anche [FromBody] se vuoi mettere un tipo di valore nel corpo di una richiesta.

+0

Grazie per il link per altre modifiche RC. Stavo cercando un elenco completo come questo per un po '. Sembra che io abbia molti attributi da aggiungere :) –

2

Stavamo vedendo la stessa cosa. Nel nostro caso il problema era un oggetto complesso passato in un metodo get. Dovevamo aggiungere un attributo [FromUri] nel parametro a quel metodo.

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) 
    { 
     // ... 
    } 
}