web-dev-qa-db-ja.com

jsonを使用して複合型をASP.NETMVCコントローラーに渡す方法

ユーザーが新しいウィジェットのデータを入力/編集できるビューがあります。そのデータを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を使用してデータを「インターセプト」し、コントローラーメソッドが呼び出される前にデータをウィジェットオブジェクトに逆シリアル化する方法はありますか?

32
MrDustpan

ジェフに感謝します、それは私を正しい道に導いた。 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; }
    }
}
25
MrDustpan

MrDustpanのソリューションでは)パラメーターnameMVCアクションメソッドのwidgetは、ASPXファイルのname属性で使用されているプレフィックスと一致する必要があります。

そうでない場合、Actionメソッドは常にnullオブジェクトを受け取ります。

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

Phil Haack あります 良いブログ投稿 役立つかもしれないモデルバインディングについて。ここで話していることを100%ではありませんが、DefaultModelBinderについて全体的に理解しやすくなると思います。

4
Jeff Sheldon

あなたがしたいのは、バックエンドオブジェクトが構造化されているのと同じ方法でjavascriptフォームオブジェクトを構造化することです。

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

次に、toJSONプラグインを使用して、上記の文字列に変換します。この文字列をバックエンドに送信し、JayRockライブラリなどを使用して新しいウィジェットオブジェクトに変換します。

2
Sugendran