2012-08-02 8 views
8

Tengo algunos datos "Foo" que quiero pasar del navegador al servidor y recuperar las estadísticas pronosticadas en base a la información contenida en foo.¿Cómo pasar el modelo complejo de cliente a servidor?

$.ajax({ 
     type: 'GET', 
     url: "/api/predictedStats/", 
     data: "foo=" + ko.toJSON(foo, fooProperties), 
     contentType: 'application/json; charset=utf-8', 
     dataType: 'json', 
     success: function(data) { 
     return _this.viewModel.setPredictedStats(data); 
     }, 
     error: function(jqXHR, statusText, errorText) { 
     return _this.viewModel.setErrorValues(jqXHR, errorText); 
     } 
    }); 

Creé un controlador de estadísticas predicho y metodo tomando un argumento de Foo.

public class PredictedStatsController : ApiController 
{ 
    public PredictedStats Get(Foo foo) 
    { 
     return statsService.GetPredictedStats(foo); 
    } 
} 

Adherir un punto de interrupción en el método Get Veo que el objeto Foo siempre es nulo. No hay errores lanzados desde el registro de rastreo webapi solo en las siguientes líneas.

WEBAPI: opr[FormatterParameterBinding] opn[ExecuteBindingAsync] msg[Binding parameter 'foo'] status[0] 
WEBAPI: opr[JsonMediaTypeFormatter] opn[ReadFromStreamAsync] msg[Type='foo', content-type='application/json; charset=utf-8'] status[0] 
WEBAPI: opr[JsonMediaTypeFormatter] opn[ReadFromStreamAsync] msg[Value read='null'] status[0] 

no tengo el envío de los datos a través de una entrada al controlador Foo para crear el objeto de Foo en el servidor así que puedo decir que no hay nada malo con el JSON creado clientside problema.

Buscando en el violín el resultado obtenido es similar al siguiente donde jsondata es el objeto foo.

GET /api/predictedStats?foo={jsondata} HTTP/1.1 

¿Esto es posible o estoy haciendo todo lo contrario?

Gracias Neil


EDIT: Siento que casi conseguí este trabajo con el siguiente

public PredictedStats Get([FromUri]Foo foo) 
{ 
    return statsService.GetPredictedStats(foo); 
} 

El objeto foo iba a volver bien, pero no hay propiedades de Foo se está poblando correctamente.


Por el momento he recurrido a la utilización de un post con datos idénticos cerca simplemente dejar caer el "foo =" y esto está funcionando muy bien.

No estoy seguro de si el POST o el GET se deben utilizar en este caso, pero sería interesante saberlo.


También encontraron esta http://bugs.jquery.com/ticket/8961 lo que parece sugerir que no se puede adjuntar un cuerpo a una solicitud GET con jQuery por lo POST es probablemente la única opción sensata

Respuesta

6

Casi haces allí :)

Cuando usa [FromUri] (que debe usar para objetos 'complejos' porque de manera predeterminada la API Web no 'vincula' objetos complejos, siempre busca deserializarlos del cuerpo) no necesita pasar param= en el Uri: acaba de pasar los miembros del valor como parámetros de cadena de consulta. Eso es 'member1=value&member2=value' - donde member1 y member2 son miembros de Foo.

Nota: no hay 'error' en jQuery: mientras que la especificación HTTP no prohíbe un cuerpo de solicitud, es probable que el navegador sí (y si ese es el caso, jQuery no puede enviarlo), y es Es más que probable que un servidor nunca lo lea de todos modos. Simplemente no es una práctica aceptada. También tiene problemas interesantes con el almacenamiento en caché, ya que un navegador no almacenará en caché un POST, PUT, DELETE, etc., sino que almacenará un GET en caché si los encabezados de respuesta no lo prohíben, lo que podría tener graves efectos secundarios para una aplicación clienteTe recomiendo que consultes este SO: HTTP GET with request body para obtener más información y algunos enlaces útiles sobre este tema.

Del mismo modo, cuando utiliza jQuery, tampoco necesita convertir el objeto a JSON, simplemente pase el objeto javascript en el data miembro de las opciones y jQuery lo convierte en el formato correcto.

O debería ser así, Web API entiende el formato al que JQuery lo pasa.

+1

Gracias, me estaba rascando la cabeza por qué un parámetro 'objeto complejo' no se llenó aunque lo decoré con '[FromUri]'. Traté de pasar en json, p. ? param = {Name: Foo} que no funcionó, tuve que cambiarlo a? Name = Foo como dijiste. Tenga en cuenta que si tiene varios parámetros de objetos complejos '[FromUri]', debe asegurarse de que no tengan propiedades con el mismo nombre, o terminará con el mismo valor de propiedad asignado a ambas instancias. –

+2

Tenga en cuenta que un simple 'public string member1;' no funcionará y 'member1' todavía será' null'. Conviértelos en ** propiedades ** y funcionará bien. – Thomas

+0

sobre que tienen que ser propiedad ... ¿por qué no lo leí hace 4 horas? Habla de sentirse estúpido, gracias Thomas por este simple pero tan perfecto comentario. –

Cuestiones relacionadas