Как передать сложный тип с помощью json в контроллер ASP.NET MVC - PullRequest
32 голосов
/ 06 ноября 2008

У меня есть вид, который позволяет пользователю вводить / редактировать данные для нового виджета. Я хотел бы сформировать эти данные в объект json и отправить их на мой контроллер через AJAX, чтобы я мог выполнить проверку на сервере без обратной передачи.

У меня все работает, но я не могу понять, как передать данные, чтобы мой метод контроллера мог принимать сложный тип виджета вместо отдельных параметров для каждого свойства.

Итак, если это мой объект:

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

Я бы хотел, чтобы мой метод контроллера выглядел примерно так:

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

В настоящее время мой jQuery выглядит так:

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

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

Моя форма (Form1) имеет поле ввода для каждого свойства в виджете (Id, Name, Price). Это прекрасно работает, но в конечном итоге каждое свойство Widget передает в качестве отдельного параметра моему методу контроллера.

Есть ли способ, которым я мог бы "перехватить" данные, возможно, используя атрибут ActionFilterAttribute, и десериализовать его в объект Widget перед вызовом моего метода контроллера?

Ответы [ 4 ]

25 голосов
/ 06 ноября 2008

Спасибо, Джефф, это привело меня на правильный путь. DefaultModelBinder достаточно умен, чтобы сделать все волшебство для меня ... моя проблема была в моем типе виджета. В спешке, мой тип был определен как:

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

Обратите внимание, что тип имеет открытые поля вместо открытых свойств. Как только я изменил их на свойства, это сработало. Вот окончательный исходный код, который работает правильно:

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; }
    }
}
6 голосов
/ 21 января 2009

Обратите внимание, что (в решении MrDustpan ) параметр name widget в методе действия MVC должен совпадать с префиксом, используемым в name атрибут в файле ASPX.

Если это не так, метод Action всегда получит объект null .

<input type="text" name="widget.Text" value="Hello" /> - OK
<input type="text" name="mywidget.Text" value="Hello" /> - FAILS
4 голосов
/ 06 ноября 2008

Фил Хаак имеет хорошее сообщение в блоге о привязке модели, которая может быть полезной. Не на 100% то, о чем вы здесь говорите, но я думаю, что это может дать вам более полное представление о DefaultModelBinder.

2 голосов
/ 06 ноября 2008

То, что вы хотите сделать, это структурировать ваш объект формы javascript таким же образом, как и ваш внутренний объект:

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

Затем используйте плагин toJSON, чтобы преобразовать его в приведенную выше строку. Вы отправляете эту строку в свой бэкэнд и используете что-то вроде библиотек JayRock для преобразования ее в новый объект Widget.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...