Estoy buscando una solución para Publicar una serie de objetos para MVC3 a través de JSON.

Código de ejemplo en el que estoy trabajando fuera de:
http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx

JS:

var data = { ItemList: [ {Str: 'hi', Enabled: true} ], X: 1, Y: 2 };

$.ajax({
    url: '/list/save',
    data: JSON.stringify(data),
    success: success,
    error: error,
    type: 'POST',
    contentType: 'application/json, charset=utf-8',
    dataType: 'json'
});

ListViewModel.cs:

public class ListViewModel
{
    public List<ItemViewModel> ItemList { get; set; }
    public float X { get; set; }
    public float Y { get; set; }
}

ItemViewModel.cs:

public class ItemViewModel
{
    public string Str;   //originally posted with: { get; set; }
    public bool Enabled; //originally posted with: { get; set; }
}

ListController.cs:

public ActionResult Save(ListViewModel list)
{
    //Do something
}

El resultado de este POST:

lista se establece, para un ListViewModel

Sus propiedades X e y se establecen

El subyacente ItemList se establece la propiedad

El ItemList contiene un elemento, como debe

El elemento en que ItemList no está inicializada. Str es nulo y Habilitado es falso.

Dicho de otra manera, esto es lo que me sale en MVC3 del modelo de enlace:

list.X == 1
list.Y == 2
list.ItemList != null
list.ItemList.Count == 1
list.ItemList[0] != null
list.ItemList[0].Str == null

Parece el MVC3 JsonValueProvider no funciona para objetos complejos. ¿Cómo puedo conseguir que esto funcione? Necesito modificar la existente MVC3 JsonValueProvider y solucionarlo? Si es así, ¿cómo puedo acceder a la misma y a reemplazar en un MVC3 proyecto?

Relacionados con la pregunta de StackOverflow ya he perseguido en vano:

Asp.net Mvc Ajax Json (Matriz de correos)
Utiliza MVC2 y mayores basada en la forma de codificación que falla con un objeto que contiene una matriz de objetos (JQuery no puede codificar correctamente).

Publicar un array de objetos complejos con JSON, JQuery para ASP.NET Controlador MVC
Usa un hack que me gustaría evitar en el que el Controlador recibe en su lugar una cadena sin formato que luego manualmente deserializa mismo, en lugar de aprovechar el marco.

MVC3 RC2 JSON Post de Enlace no funciona correctamente
No tenía su tipo de contenido conjunto, ubicado en mi código.

Cómo publicar una matriz de objetos complejos con JSON, jQuery para ASP.NET Controlador MVC?
Este pobre hombre tuvo que escribir una JsonFilter sólo para analizar una matriz. Otro hack prefiero evitar.

Así, ¿cómo puedo hacer que esto suceda?

  • Actualización: he cavado en la JsonValueProviderFactory. Se consume el «str» la propiedad y la añade a la copia de Diccionario como Clave=»ItemList[0].Str», Value=»hola», lo que parece correcto. ModelBinder?
  • Usted señor, acaba de recibir una upvote y una de las estrellas por su excelente ejecución de un desbordamiento de pila-pregunta! 🙂
  • Mismo aquí, este fue el que finalmente hizo el trabajo para mí. Gracias!

6 Comentarios

  1. 43

    Además { get; set; }, estas son algunas de las condiciones para JSON Enlace de Apoyo:

    1. Esta es la nueva característica en ASP.NET MVC 3 (Ver «JavaScript y AJAX Mejoras«).
    2. El objeto JSON a las cuerdas (‘X’, ‘Y’, ‘Str’, y ‘Habilitado’) debe coincidir con ViewModel propiedades del objeto.
    3. ViewModel propiedades del objeto debe tener { get; set; } método.
    4. Debe especificar el Tipo de Contenido como «application/json» en la solicitud.
    5. Si aún no funciona, compruebe la cadena JSON para asegurarse de que es válido.

    Leer más en mi post.

    Espero que ayude!

    • Gracias por la información. Resulta que yo tenía y la llamada ajax que no especifique el ‘application/json’ tipo de contenido, y todo funcionó a la excepción de rellenar las propiedades de elemento de matriz!
    • el problema para mí era el contentType, gracias
    • Absoluta, clara y concisa visión general de los requisitos para json esperando apoyo para trabajar fuera de la caja w/asp.net mvc. Una referencia valiosa y de gran respuesta.
    • Gracias! Finalmente consiguió trabajo
  2. 30

    El problema era que las propiedades de los modelos que estaban en la Lista de no tener get/set en sus propiedades públicas. Dicho de otra manera, MVC3 automático de JSON enlace sólo funciona en las propiedades del objeto que han get y set.

    Esto no se unen:

    public string Str;

    Esto se unen:

    public string Str { get; set; }
  3. 29

    Que extraño. Soy incapaz de reproducir su comportamiento. Aquí está mi configuración (ASP.NET MVC 3 RTM):

    Modelo:

    public class ItemViewModel
    {
        public string Str { get; set; }
        public bool Enabled { get; set; }
    }
    
    public class ListViewModel
    {
        public List<ItemViewModel> ItemList { get; set; }
        public float X { get; set; }
        public float Y { get; set; }
    }

    Controlador:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    
        [HttpPost]
        public ActionResult Save(ListViewModel list)
        {
            return Json(list);
        }
    }

    Vista:

    @{
        ViewBag.Title = "Home Page";
    }
    
    <script type="text/javascript">
        $(function () {
            var data = { ItemList: [{ Str: 'hi', Enabled: true}], X: 1, Y: 2 };
    
            $.ajax({
                url: '@Url.Action("save", "home")',
                data: JSON.stringify(data),
                type: 'POST',
                contentType: 'application/json',
                dataType: 'json',
                success: function (result) {
                    alert(result.ItemList[0].Str);
                }
            });
        });
    </script>

    Ejecución de este alertas "hi" y en el interior de la Save acción, todo está correctamente inicializado.

    Y sólo para el registro de lo que no funciona son los Diccionarios. He abre un ticket sobre el tema.

    • Extraño. Gracias por mirar en esta. Para lo que vale, estoy usando la versión de MVC aquí: asp.net/mvc/mvc3 – Es posible, estamos utilizando diferentes versiones de MVC, aunque sería extraño si esto se puso PEOR en la versión final. Voy a tratar de aislar las cosas un poco mejor y para verificar mi pregunta afirmaciones antes de la celebración de este respondió o no.
    • He encontrado el problema. El interior del modelo fue el uso de las propiedades públicas que no han get/set. Voy a arreglar la cuestión de ampliar el problema.
    • TODOS: Nota esta línea >>> contentType: ‘application/json’
    • +1: Gracias por salir de su camino en este (con los ejemplos de código). Me ayudó a mí, y yo ni siquiera era el OP.
    • Me gusta este patrón para hacer peticiones json y es agradable ver que reproduce de forma clara, simple y sencillo, sencillo y fácil de analizar. Yo podría rly utilizar un resharper macro para agregar rápidamente las piezas para un nuevo extremo a extremo json llamada; completa w/modelo de vista, como me parece que el uso de este patrón más y más últimamente.
  4. 3

    Tuve un problema similar, y se encontró que para un objeto complejo, los valores numéricos se estaban poniendo perdido. Fueron llegando como ceros.
    es decir,

        var person = {
            Name: "john",
            Age: 9
        }

    estaba siendo recibida por el controlador MVC como un objeto de la Persona en el que las propiedades estaban pobladas como Name=John y Age=0.

    Luego hice el valor de Edad en Javascript para ser de la cadena… es decir,

        var person = {
            Name: "john",
            Age: "9"
        }

    Y esto salió muy bien…

  5. 0

    Porque la MVC ligantes tipo de chupar. Sin embargo, es que funcionan bastante bien si todos JSON valores venir como una cadena.

    En JS si usted hace esto

    var myObject = {thisNumber:1.6};
    
    myObject.thisNumber=myObject.thisNumber-.6;

    Se evaluará a 1 no a 1.0

    Así que cuando usted envía al servidor intentará enlazar a un flotador de ese nombre y no encontrarlo, ya que se llegó a más de 1 en lugar de 1.0. Su muy cojo y el loco que MS ingenieros no vino para arriba con una solución predeterminada para este. Creo que si de cadena de todo lo que los enlaces están lo suficientemente inteligente como para encontrar las cosas.

    Así que antes de enviar los datos a través de ejecutarlo a pesar de que un stringifier que también convertir todos los valores de cadenas de caracteres.

  6. 0

    Todas las respuestas anteriores fueron grandes que me apunte a la solución de los problema similar. Yo tenía que escribir x-www-form-urlencoding en lugar de application/json (opción por defecto si contentType parámetro que falta) para ser capaz de pasar __RequestVerificationToken y, simultáneamente, se enfrentan con el problema cuando las propiedades de objeto de estar en la matriz no se unen a sus valores. La manera de resolver el problema es entender el trabajo interno de cuaderno de modelo MVC.

    Así que, básicamente, cuando usted necesita el suministro de verificación de token que se limita con la validación de atributo. Y usted debe proporcionar el token como el parámetro no como una parte de la JSON-objeto que se está enviando. Si no desea utilizar ValidateAntiForgeryToken, usted podría conseguir a lo largo con JSON.stringify. Pero si usted, usted no puede pasar el token.

    Me olfateó el tráfico de backend, cuando ContentType fue x-www-form-urlencoding y me comentó que mi matriz de objetos complejos fue serializado a algo así como que: klo[0][Count]=233&klo[0][Blobs]=94. Esta matriz inicialmente era parte de un objeto raíz, digamos que algunos de modelo. Parecía como que: model.klo = [{ Count: 233, Blobs: 94}, ...].

    En el backend lado este klo propiedad fue la creación por MVC cuaderno con los mismos elementos que contar que me envió. Pero estos elementos no obtener los valores de sus propiedades.

    SOLUCIÓN

    Para lidiar con esto me excluidos klo propiedad a partir del modelo de objetos en el lado del cliente. En el ajax función escribí este código:

    data: $.param(model) + "&" + arrayOfObjectsToFormEncoding("klo", [{ Count: 233, Blobs: 94}, ...])
    ....
    
        function arrayOfObjectsToFormEncoding (modelPropertyName, arrayOfObjects) {
            var result = "";
            if (arrayOfObjects && typeof arrayOfObjects == "object") {
                for (var i = 0; i < arrayOfObjects.length; i++) {
                    var obj = arrayOfObjects[i];
                    if (obj) {
                        for (var p in obj) {
                            if (obj.hasOwnProperty(p)) {
                                result += encodeURIComponent(modelPropertyName + "[" + i + "]." + p) + "=" + encodeURIComponent(obj[p]) + "&";
                            }
                        }
                    }
                }
            }
    
            if (result[result.length - 1] == "&") {
                result = result.substr(0, result.length - 1);
            }
    
            return result;
        }

    La función transforma la matriz de objeto complejo en la forma que es reconocido por MVC-cuaderno. La forma es klo[0].Count=233&klo[0].Blobs=94.

Dejar respuesta

Please enter your comment!
Please enter your name here