2012-06-22 16 views
5

Ricevo quello che considero un problema di binding strano nell'API Web RC ASP.NET MVC 4. Ho un metodo destinato ad accettare richieste di posta dal client. Il problema è che nessuno dei parametri è vincolante quando viene chiamato il metodo post, arrivo al punto di interruzione sulla riga di lancio e il nome, entrambi i messaggi di posta elettronica sono nulli. Se cambio il tipo della richiesta in GET in JavaScript, la funzione Get di seguito viene chiamata con i parametri associati.ASP.NET MVC 4 RC API Web Legame dei problemi Numero

Perché i parametri non riescono a eseguire il binding per il metodo Post e come posso risolvere questo problema?

send: function(evt) { 
    evt.preventDefault(); 
    $.ajax({ 
     url: '/api/person', 
     data: this.model.toJSON(), 
     type: "POST", 
     dataType: "json", 
     success: function(data) { 
      console.log("Success"); 
     }, 
     error: function(data) { 
      console.log("Error"); 
     } 
    }); 
    } 

Quello che segue è l'azione del controller:

public void Get(string name, string email) { 
    throw new NotImplementedException(); 
} 

public void Post(string name, string email) { 
    throw new NotImplementedException(); 
} 

Note:

  • sto usando tutti i valori predefiniti per ASP.NET MVC 4 RC Web API (in modo che il deserializzatore dovrebbe essere Json.NET)
  • La scheda di rete di Chrome sul debugger JS mostra correttamente i parametri nei dati del modulo nel post.

risposta

13

A differenza di MVC (pagine Web), tipi di parametri semplici will not, by default, bind from the post body but instead from the URI. Quindi, con il tuo codice così com'è, devi passare i parametri name e email nella stringa di query o come parametri del percorso.

Tuttavia, questo può essere facilmente risolto creando un tipo di modello (in vernacolo MVC) e utilizzando quello per i parametri del metodo. In realtà si può quindi utilizzare per entrambi (nel caso in cui hai dato), se quindi si utilizza [FromUri] sul metodo get:

public class SomeParams { 
    public string name { get; set; } 
    public string email { get; set; } 
} 

//now an alternative way to write the Get method 
public MyResult Get([FromUri] SomeParams p){ 
    //members are bound from the query string (more like MVC traditional binding) 
    //note - as in MVC, SomeParams will need a default constructor for this to work. 
} 

public PostResult Post(SomeParams p){ 
    //'p' is bound from your JSON (assuming correct format) 
    //because 'complex' types are deserialized using formatters 
    //only one object can be read from the body with a formatter in Web API 
    //as the request body is not buffered; unlike MVC. 
} 

ho bloccato in tipi di ritorno per i metodi solo perchè avrebbero bisogno di restituire qualcosa!

Consiglio davvero di leggere l'articolo di Mike Stall che linko sopra (e molti dei suoi altri).

È allettante presupporre che l'API Web, poiché condivide gli stessi paradigmi e persino i nomi di classi di MVC, è in realtà la stessa di MVC, ma non lo è. Inizialmente mi chiedevo perché questo fosse il caso (dato che ho scritto molti servizi REST su MVC personalmente e ho trovato che fosse davvero figo, una volta che hai scritto alcune classi di utilità e miglioramenti di classe base), ma hanno preso in considerazione le sfide della scrittura di un'API Web e penso che probabilmente abbiano ragione ad aver apportato le modifiche all'approccio che hanno.

Tuttavia, ciò significa che dobbiamo prendere alcune cose che ora possiamo dare per scontate e ri-apprenderle per l'API Web.

+0

Il parametro get non è nullo, infatti non esiste nemmeno. Potrei non essere stato chiaro ma è solo lì per illustrare che la funzionalità funziona su GET e non su POST. – Cody

+1

Okay - beh, va bene allora :). In breve, tuttavia, se si vincolano più parametri dal corpo della richiesta, in pratica la cosa più semplice da fare è scrivere un tipo di modello semplice come ho mostrato. –

+0

Grazie per il link all'articolo di Mike Stall, è stato molto istruttivo su cosa sta succedendo. Avevo appena ipotizzato che le API Web usassero esattamente la stessa strategia di binding di MVC. Creare una classe personalizzata per ricevere i parametri ha funzionato come un incantesimo, non sono un fan di questa soluzione, ma non riesco a capire perché, quindi probabilmente sono solo testardo. :) In ogni caso è la soluzione che userò. Grazie!:) – Cody

Problemi correlati