Отправить массив объектов через JSON в ASP.Net MVC3



Я ищу решение для размещения массива объектов в MVC3 через JSON.



пример кода, над которым я работаю:
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<ItemViewModel> 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
}


результат этого поста:



список установлен, в a ListViewModel

Его свойства X и Y установлены

Базовое свойство ItemList имеет значение

ItemList содержит один элемент, как и должно

Элемент в этом списке элементов является неинициализированным. Str имеет значение null, а Enabled-false.



другими словами, это то, что я получаю от привязки модели MVC3:



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


похоже, что MVC3 JsonValueProvider не работает для сложных объектов. Как мне заставить это работать? Нужно ли мне изменять существующий MVC3 JsonValueProvider и исправить это? Если да, то как мне добраться до него и заменить его в проекте MVC3?



связанные с StackOverflow вопросы, которые я уже преследовал безрезультатно:



Asp.net MVC Ajax Json (post Array)
Использует mvc2 и более старое кодирование на основе формы-этот подход не работает с объектом, который содержит массив объектов (JQuery не может правильно его кодировать).



разместить массив сложных объектов с помощью JSON, JQuery в ASP.NET контроллер MVC
Использует Хак, которого я хотел бы избежать где контроллер вместо этого получает простую строку, которую он затем вручную десериализует сам, а не использует фреймворк.



MVC3 RC2 JSON Post Binding не работает правильно
У него не было своего набора типов контента-он установлен в моем коде.



как разместить массив сложных объектов с помощью JSON, jQuery в ASP.NET контроллер MVC?
Этот бедный парень должен был написать JsonFilter только для разбора массива. Другого взлома я бы предпочел избежать.



Итак, как мне это сделать случилось?

623   6  

6 ответов:

кроме { get; set; }, вот некоторые из условий поддержки привязки JSON:

  1. Это новая функция в ASP.NET MVC 3 (см. "улучшения JavaScript и AJAX").
  2. строки объекта JSON (’X‘,’ Y‘,’ Str ‘и’ Enabled') должны соответствовать свойствам объекта ViewModel.
  3. свойства объекта ViewModel должны иметь { get; set; } метод.
  4. необходимо указать тип контента как "application / json" в поле запрос.
  5. если он все еще не работает, проверьте строку JSON, чтобы убедиться, что она действительна.

подробнее на мой пост.

надеюсь, что это поможет!

проблема заключалась в том, что свойства в моделях, которые были в списке, не имели get/set для их общих свойств. Другими словами, автоматическая привязка JSON MVC3 работает только со свойствами объекта, которые имеют get и set.

это не связывает:

public string Str;

Это позволит связать:

public string Str { get; set; }

Это странно. Я не могу воспроизвести поведение. Вот моя настройка (ASP.NET MVC 3 RTM):

модель:

public class ItemViewModel
{
    public string Str { get; set; }
    public bool Enabled { get; set; }
}

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

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

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

была получена путем контроллера MVC в качестве объекта человека, где свойства были заселены как Name=John и Age=0.

затем я сделал значение возраста в Javascript строкой... то есть

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

и это просто замечательно...

Это потому, что MVC-связующие вроде сосут. Тем не менее, они работают довольно хорошо, если все значения JSON приходят в виде строки.

в JS, если вы сделаете это

var myObject = {thisNumber:1.6};

myObject.thisNumber=myObject.thisNumber-.6;

он будет оценивать до 1, а не до 1,0

поэтому, когда вы отправили его на сервер, он попытается привязать к поплавку этого имени, и он не найдет его, так как он перешел на 1 вместо 1.0. Его очень хромой и сумасшедший, что инженеры MS не придумали решение по умолчанию для этого. Я нахожу, если вы строите все привязки достаточно умны, чтобы найти вещи.

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

все предыдущие ответы были велики, чтобы указать мне на решение подобной проблемы. Я должен был опубликовать x-www-form-urlencoding вместо application/json (опция по умолчанию, если параметр contentType отсутствует), чтобы иметь возможность передать __RequestVerificationToken и одновременно столкнулся с проблемой, когда свойства объекта в массиве не связывают свои ценности. Способ решить эту проблему-понять внутреннюю работу MVC model binder.

Итак, в основном, когда вам нужно предоставить маркер проверки, вы ограничены с атрибутом проверки. И вы должны предоставить токен в качестве параметра, а не как часть JSON-объекта, который вы отправляете. Если вы не будете использовать ValidateAntiForgeryToken, вы могли бы поладить с JSON.преобразовать в строки. Но если бы вы захотели, то не смогли бы передать жетон.

я нюхал трафик на бэкэнд, когда ContentType был x-www-form-urlencoding и я заметил, что мой массив сложных объектов был сериализован в что-то вроде этого: klo[0][Count]=233&klo[0][Blobs]=94. Этот массив изначально был частью корневого объекта, скажем, некоторой модели. Это выглядело вот так:model.klo = [{ Count: 233, Blobs: 94}, ...].

на задней стороне это klo свойство создавалось MVC binder с тем же количеством элементов, которое я отправил. Но сами эти элементы не получили значений для своих свойств.

решение

чтобы справиться с этим я исключил klo свойство от объекта модели на стороне клиента. В Я написал этот код:

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

функция преобразует массив сложного объекта в форму, которая распознается MVC-связующим. Форма-это klo[0].Count=233&klo[0].Blobs=94.

Comments

    Ничего не найдено.