Подтвердить что ты не робот

Как передать сложный тип с помощью json для ASP.NET MVC-контроллера

У меня есть представление, которое позволяет пользователю вводить/редактировать данные для нового виджета. Я хотел бы сформировать эти данные в 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). Это отлично работает, но в конечном итоге передает каждое свойство виджета в качестве отдельного параметра для моего метода контроллера.

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

4b9b3361

Ответ 1

Спасибо Джеффу, что привело меня к правильному пути. 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; }
    }
}

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

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

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

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