2008-11-06 11 views
32

Ich habe eine Ansicht, mit der ein Benutzer Daten für ein neues Widget eingeben/bearbeiten kann. Ich möchte diese Daten in einem JSON-Objekt bilden und über AJAX an meinen Controller senden, damit ich die Validierung auf dem Server ohne Postback durchführen kann.Wie komplexen Typ übergeben mit Json zu ASP.NET MVC-Controller

Ich habe alles funktioniert, aber ich kann nicht herausfinden, wie die Daten übergeben werden, so dass meine Controller-Methode einen komplexen Widget-Typ statt einzelner Parameter für jede Eigenschaft akzeptieren kann.

Also, wenn dies mein Ziel ist:

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

ich mein Controller-Methode möchte etwas wie folgt aussehen:

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

Derzeit sieht mein jQuery wie folgt aus:

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

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

Mein Formular (Form1) hat ein Eingabefeld für jede Eigenschaft auf dem Widget (ID, Name, Preis). Das funktioniert großartig, aber letztendlich übergibt es jede Eigenschaft des Widgets als einen separaten Parameter an meine Controller-Methode.

Gibt es eine Möglichkeit, die Daten "abzufangen", vielleicht mit einem ActionFilterAttribute, und es zu einem Widget-Objekt zu deserialisieren, bevor meine Controller-Methode aufgerufen wird?

Antwort

24

Dank Jeff, das hat mich auf den richtigen Weg gebracht. Der DefaultModelBinder ist intelligent genug, um all die Magie für mich zu tun ... mein Problem war in meinem Widget-Typ. In meiner Eile wurde mein Typ definiert als:

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

Beachten Sie, dass der Typ öffentliche Felder anstelle von öffentlichen Eigenschaften hat. Sobald ich diese zu Eigenschaften änderte, funktionierte es. Hier ist die letzte Quellcode, der richtig funktioniert:

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; } 
    } 
} 
+3

Ehrfürchtig, froh, dass Sie es behoben haben. Und danke, dass du gepostet hast, wie du es repariert hast, das wird anderen in Zukunft viel helfen! –

+1

Öffentliche Felder sind der Teufel in .NET. Sie brechen alles. ALLES, was ich Ihnen erzähle! – Will

+0

Danke. Das hat mir geholfen. –

2

Was Sie tun möchten, ist Struktur Ihr Javascript Formularobjekt in der gleichen Art und Weise wird Ihr Backend-Objekt strukturiert:

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

Dann nutzen Sie die toJSON Plugin in die obige Zeichenfolge zu konvertieren. Sie senden diese Zeichenfolge an Ihr Backend und verwenden so etwas wie die JayRock-Bibliotheken, um sie in ein neues Widget-Objekt zu konvertieren.

4

Phil Haack hat a good blog post über Modellbindung, die hilfreich sein könnte. Nicht 100%, worüber du hier redest, aber ich denke, es könnte dir ein besseres Verständnis über den DefaultModelBinder geben.

6

Beachten Sie, dass (in MrDustpan der Lösung) der Parameter NameWidget in der MVC Action-Methode muss mit dem Präfix in der Name attri übereinstimmen bute in der ASPX-Datei. Wenn das nicht der Fall ist, erhält die Aktionsmethode immer ein Objekt null.

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

Ausgezeichneter Punkt und leicht übersehen. Scheint auch die Groß-/Kleinschreibung zu beachten. –

Verwandte Themen