Pregunta Cómo pasar el tipo complejo usando json al controlador ASP.NET MVC


Tengo una vista que permite a un usuario ingresar / editar datos para un nuevo widget. Me gustaría formar esos datos en un objeto JSON y enviarlos a mi controlador a través de AJAX para que pueda hacer la validación en el servidor sin una devolución de datos.

Lo tengo todo funcionando, excepto que no puedo descifrar cómo pasar los datos para que mi método de control pueda aceptar un tipo de widget complejo en lugar de parámetros individuales para cada propiedad.

Entonces, si este es mi objetivo:

public class Widget
{
   public int Id { get; set; }
   public string Name { get; set; }
   public decimal Price { get; set; }
}

Me gustaría que mi método de control se vea así:

public JsonResult Save(Widget widget)
{
   ...
}

Actualmente, mi jQuery se ve así:

var formData = $("#Form1").serializeArray();

$.post("/Widget/Save",
   formData,
   function(result){}, "json");

Mi formulario (Form1) tiene un campo de entrada para cada propiedad en el Widget (Id, Nombre, Precio). Esto funciona muy bien, pero finalmente pasa cada propiedad del Widget como un parámetro separado a mi método de controlador.

¿Hay alguna manera de que pueda "interceptar" los datos, tal vez usando un ActionFilterAttribute, y deserializarlos en un objeto Widget antes de que se llame a mi método de controlador?


32
2017-11-06 05:19


origen


Respuestas:


Gracias Jeff, eso me puso en el camino correcto. El DefaultModelBinder es lo suficientemente inteligente como para hacer toda la magia para mí ... mi problema estaba en mi tipo de widget. En mi prisa, mi tipo se definió como:

public class Widget
{
   public int Id;
   public string Name;
   public decimal Price;
}

Tenga en cuenta que el tipo tiene campos públicos en lugar de propiedades públicas. Una vez que los cambié a propiedades, funcionó. Aquí está el código fuente final que funciona correctamente:

Widget.aspx:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Widget.aspx.cs" Inherits="MvcAjaxApp2.Views.Home.Widget" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <script src="../../Scripts/jquery-1.2.6.js" type="text/javascript"></script>   
    <script type="text/javascript"> 
    function SaveWidget()
    {
        var formData = $("#Form1").serializeArray();

        $.post("/Home/SaveWidget",
        formData,
        function(data){
            alert(data.Result);
        }, "json");
    }
    </script>
    <form id="Form1">
        <input type="hidden" name="widget.Id" value="1" />
        <input type="text" name="widget.Name" value="my widget" />
        <input type="text" name="widget.Price" value="5.43" />
        <input type="button" value="Save" onclick="SaveWidget()" />
    </form>
</asp:Content>

HomeController.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

namespace MvcAjaxApp2.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewData["Title"] = "Home Page";
            ViewData["Message"] = "Welcome to ASP.NET MVC!";
            return View();
        }

        public ActionResult About()
        {
            ViewData["Title"] = "About Page";
            return View();
        }

        public ActionResult Widget()
        {
            ViewData["Title"] = "Widget";
            return View();
        }

        public JsonResult SaveWidget(Widget widget)
        {
            // Save the Widget
            return Json(new { Result = String.Format("Saved widget: '{0}' for ${1}", widget.Name, widget.Price) });
        }
    }
    public class Widget
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
}

25
2017-11-06 15:29



Tenga en cuenta que (en MrDustpan's solución) el parámetro nombre  widget en el método MVC Action debe coincidir con el prefijo utilizado en nombre atributo en el archivo ASPX.

Si este no es el caso, el método de Acción siempre recibirá un nulo objeto.

<input type="text" name="widget.Text" value="Hello" /> - OK
<input type="text" name="mywidget.Text" value="Hello" /> - FAILS

6
2018-01-21 02:17



Phil Haack tiene una buena publicación de blog sobre el modelo de encuadernación que podría ser útil. No es el 100% de lo que estás hablando aquí, pero creo que podría darte una mejor comprensión general sobre DefaultModelBinder.


4
2017-11-06 14:04



Lo que quiere hacer es estructurar su objeto de formulario de JavaScript de la misma manera que su objeto de fondo está estructurado:

{ Id : "id", Name : "name", Price : 1.0 }

Luego use el complemento toJSON para convertirlo en la cadena anterior. Usted envía esta cadena a su servidor y utiliza algo como las bibliotecas JayRock para convertirlo en un nuevo objeto Widget.


2
2017-11-06 05:43