Veröffentlichen Sie ein Array von Objekten über JSON zu ASP.Net MVC3

Ich suche nach einer Lösung, um ein Array von Objekten an MVC3 über JSON zu senden.

Beispielcode, von dem ich arbeite: http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx

JS:

var data = { ItemList: [ {Str: 'hi', Enabled: true} ], X: 1, Y: 2 }; $.ajax({ url: '/list/save', data: JSON.stringify(data), success: success, error: error, type: 'POST', contentType: 'application/json, charset=utf-8', dataType: 'json' }); 

ListViewModel.cs:

 public class ListViewModel { public List ItemList { get; set; } public float X { get; set; } public float Y { get; set; } } 

ItemViewModel.cs:

 public class ItemViewModel { public string Str; // originally posted with: { get; set; } public bool Enabled; // originally posted with: { get; set; } } 

ListController.cs:

 public ActionResult Save(ListViewModel list) { // Do something } 

Das Ergebnis dieses POST:

Liste ist festgelegt, zu einem ListViewModel
Seine X- und Y-Eigenschaften sind festgelegt
Die zugrunde liegende ItemList-Eigenschaft ist festgelegt
Die ItemList enthält wie erwartet ein Element
Das Element in dieser ItemList ist nicht initialisiert. Str ist null und Enabled ist falsch.

Anders gesagt, das ist, was ich von der MVC3-Modellbindung bekomme:

 list.X == 1 list.Y == 2 list.ItemList != null list.ItemList.Count == 1 list.ItemList[0] != null list.ItemList[0].Str == null 

Es scheint, dass der MVC3 JsonValueProvider nicht für komplexe Objekte funktioniert. Wie bekomme ich das zum Laufen? Muss ich den vorhandenen MVC3 JsonValueProvider ändern und beheben? Wenn ja, wie komme ich dazu und ersetze es in einem MVC3-Projekt?

Verwandte StackOverflow-Fragen, die ich schon vergebens verfolgt habe:

Asp.net Mvc Ajax Json (nach Array) Verwendet MVC2 und ältere formularbasierte Kodierung – dieser Ansatz schlägt mit einem Objekt fehl, das ein Array von Objekten enthält (JQuery kann es nicht richtig kodieren).

Veröffentlichen Sie ein Array komplexer Objekte mit JSON, JQuery mit ASP.NET MVC Controller Verwendet einen Hack, den ich vermeiden möchte, wenn der Controller stattdessen eine einfache Zeichenfolge erhält, die er dann manuell deserialisiert, anstatt das Framework zu nutzen.

MVC3 RC2 JSON Post-Binding funktioniert nicht richtig Der Inhaltstyp wurde nicht festgelegt – er ist in meinem Code festgelegt.

Wie ein Array von komplexen Objekten mit JSON, jQuery zu ASP.NET MVC Controller zu buchen? Dieser arme Typ musste einen JsonFilter schreiben, nur um ein Array zu parsen. Ein weiterer Hack, den ich lieber vermeiden würde.

Also, wie mache ich das möglich?

Zusätzlich zu { get; set; } { get; set; } { get; set; } , das sind einige der Bedingungen für JSON Binding Support:

  1. Dies ist eine neue function in ASP.NET MVC 3 (siehe ” JavaScript- und AJAX-Verbesserungen “).
  2. Die Zeichenfolgen des JSON-Objekts (‘X’, ‘Y’, ‘Str’ und ‘Enabled’) müssen den Eigenschaften des ViewModel-Objekts entsprechen.
  3. Die Eigenschaften des ViewModel-Objekts müssen { get; set; } { get; set; } { get; set; } Methode.
  4. Geben Sie in der Anforderung den Inhaltstyp als “application / json” an.
  5. Wenn es immer noch nicht funktioniert, überprüfen Sie die JSON-Zeichenfolge, um sicherzustellen, dass sie gültig ist.

Lesen Sie mehr auf meinem Post .

Ich hoffe, das hilft!

Das Problem bestand darin, dass die Eigenschaften in den Modellen, die sich in der Liste befanden, ihre öffentlichen Eigenschaften nicht erhalten / festgelegt haben. Anders gesagt, die automatische JSON-Bindung von MVC3 funktioniert nur bei Objekteigenschaften, die get und gesetzt sind.

Dies wird nicht binden:

 public string Str; 

Dies wird binden:

 public string Str { get; set; } 

Das ist seltsam. Ich kann dein Verhalten nicht reproduzieren. Hier ist mein Setup (ASP.NET MVC 3 RTM):

Modell:

 public class ItemViewModel { public string Str { get; set; } public bool Enabled { get; set; } } public class ListViewModel { public List ItemList { get; set; } public float X { get; set; } public float Y { get; set; } } 

Regler:

 public class HomeController : Controller { public ActionResult Index() { return View(); } [HttpPost] public ActionResult Save(ListViewModel list) { return Json(list); } } 

Aussicht:

 @{ ViewBag.Title = "Home Page"; }  

Wenn diese Warnungen "hi" und innerhalb der Save alles korrekt initialisiert wird.

Und nur für die Aufzeichnung, was nicht funktioniert, sind Wörterbücher. Ich habe ein Ticket über das Problem geöffnet .

Ich hatte ein ähnliches Problem und stellte fest, dass die numerischen Werte für ein komplexes Objekt verfehlt wurden. Sie kamen als Nullen herein. dh

  var person = { Name: "john", Age: 9 } 

wurde vom MVC-Controller als Person-Objekt empfangen, wo die Eigenschaften als Name=John und Age=0 .

Ich habe dann den Age-Wert in Javascript auf string … gesetzt

  var person = { Name: "john", Age: "9" } 

Und das kam gut durch …

Es ist weil die MVC-Binder irgendwie saugen. Sie funktionieren jedoch ziemlich gut, wenn alle JSON-Werte als Zeichenfolge übergeben werden.

In JS, wenn Sie dies tun

 var myObject = {thisNumber:1.6}; myObject.thisNumber=myObject.thisNumber-.6; 

Es wird zu 1 nicht zu 1.0 ausgewertet

Wenn Sie es also an den Server senden, wird es versuchen, an ein Float dieses Namens zu binden, und es wird es nicht finden, da es als 1 anstelle von 1.0 kam. Es ist sehr lahm und verrückt, dass die MS-Ingenieure keine Standardlösung dafür gefunden haben. Ich finde, wenn du alles zeichnest, sind die Bindungen schlau genug, Dinge zu finden.

Bevor also die Daten gesendet werden, wird ein Stringifier ausgeführt, der auch alle Werte in Strings konvertiert.

Alle vorherigen Antworten waren großartig, um mich auf die Lösung des ähnlichen Problems hinzuweisen. Ich musste POST x-www-form-urlencoding anstelle von application/json (Standardoption, wenn contentType-Parameter fehlt) __RequestVerificationToken , um __RequestVerificationToken und gleichzeitig mit Problemen konfrontiert zu sein, wenn Objekteigenschaften im Array ihre Werte nicht binden. Der Weg zur Lösung des Problems besteht darin, die interne Arbeit des MVC-Modellbinders zu verstehen.

Also, im Grunde, wenn Sie Verifikationstoken liefern müssen, sind Sie mit validationsattribut eingeschränkt. Und Sie müssen das Token als Parameter angeben, nicht als Teil des JSON-Objekts, das Sie senden. Wenn Sie ValidateAntiForgeryToken nicht verwenden würden, könnten Sie mit JSON.stringify auskommen. Aber wenn Sie das täten, könnten Sie das Token nicht weitergeben.

Ich schnüffelte den Datenverkehr zum Backend, als ContentType x-www-form-urlencoding und ich bemerkte, dass mein Array komplexer Objekte in etwa wie x-www-form-urlencoding serialisiert wurde: klo[0][Count]=233&klo[0][Blobs]=94 . Dieses Array war ursprünglich ein Teil des Root-Objekts, sagen wir mal ein Modell. Es sah so aus: model.klo = [{ Count: 233, Blobs: 94}, ...] .

Auf der Backend-Seite wurde diese klo von MVC-Binder mit den gleichen Elementen erstellt, die ich gesendet habe. Aber diese Elemente selbst haben keine Werte für ihre Eigenschaften erhalten.

LÖSUNG

Um das zu umgehen, habe ich die klo Eigenschaft vom klo auf der Client-Seite ausgeschlossen. In der ajax function habe ich diesen Code geschrieben:

 data: $.param(model) + "&" + arrayOfObjectsToFormEncoding("klo", [{ Count: 233, Blobs: 94}, ...]) .... function arrayOfObjectsToFormEncoding (modelPropertyName, arrayOfObjects) { var result = ""; if (arrayOfObjects && typeof arrayOfObjects == "object") { for (var i = 0; i < arrayOfObjects.length; i++) { var obj = arrayOfObjects[i]; if (obj) { for (var p in obj) { if (obj.hasOwnProperty(p)) { result += encodeURIComponent(modelPropertyName + "[" + i + "]." + p) + "=" + encodeURIComponent(obj[p]) + "&"; } } } } } if (result[result.length - 1] == "&") { result = result.substr(0, result.length - 1); } return result; } 

Die function transformiert das Array komplexer Objekte in eine Form, die vom MVC-Binder erkannt wird. Die Form ist klo[0].Count=233&klo[0].Blobs=94 .