Сложная привязка списка JSON MVC3 - PullRequest
8 голосов
/ 19 марта 2012

Возникают проблемы с получением ASP.NET MVC3 для привязки моего сложного объекта JSON, который содержит список.

Вот структура, которая у меня есть для моих объектов.

public class PageModel
{
    public PageModel() { }
    public CustomObject1 CustomObject { get; set; }
    public IEnumerable<CustomObject2> Objects { get; set; }

}

public class CustomObject1
{
    public CustomObject1() { }
    [Required]
    public int CustomId1 { get; set; }
    public string CustomName { get; set; }
}

public class CustomObject2
{
    public CustomObject2() { }
    [Required]
    public int Custom2Id { get; set; }
    public CustomObject3 SubItem { get; set; }
    public int SubItemId { get; set; }
}

Вы можете предположить CustomObject3 имеет аналогичную структуру - не нужно дублировать еще один составленный класс, поэтому я полагаю, что вы можете использовать свое воображение:)

Вот Javascript / Jquery, который делает вызов POST (предположим, что все JS, ведущие кэто дает правильные данные):

//$obj1 has all data for the first object
var firstObj = { };
firstObj.CustomId1 = $obj1.Id;
firstObj.CustomName = $obj1.Name;

var i = 0;

//$objects is an array with all the data
$.each($objects, function() {
    objsArray[i] = {
    Custom2Id: $(this).Id,
    SubItemId: $(this).itemId
    };

    ++i;
});

$.ajax({
    type: 'POST',
    url: '/Action/Method',
    data: { CustomObject: firstObj, Objects: objsArray },
    //Success/error handlers here
});

И наконец (я знаю, довольно много кода) вот краткий обзор метода, который у меня есть:

public class ActionController : Controller {
    public JsonResult Method(PageModel model) {
        //Gets here - model.CustomObject is filled correctly, and model.Objects has a correct count of whatever data I passed to the method - but all of the properties are empty!
    }
}

Как я уже сказал, первыйОбъект заполнен, и все данные находятся там, когда я отлаживаю и прохожу.Если я передаю два объекта в массиве Objects в объекте JSON, я вижу Count из 2 в контроллере, но Custom2Id и SubItemId пусты.Что дает?

Когда я указываю contentType из 'application/json' в моем $.ajax вызове, MVC жалуется на передаваемые данные.Также попытался разделить параметр model в методе MVC на два отдельных параметра, но это не помогло.

Любая помощь очень ценится - это меня озадачило!

Ответы [ 2 ]

5 голосов
/ 19 марта 2012

Таким образом, решение этой конкретной проблемы представляет собой комбинацию двух или более решений, найденных в других местах SO (одним из них, возможно, является ответ Якуба, вращающийся вокруг использования универсального типа коллекции - IEnumerable - в отличие от более конкретный - List).

Во-первых, нет необходимости изменять код на стороне сервера - все хорошо на этом фронте. Все изменения, которые необходимо внести, относятся на стороне клиента, и в частности то, как jQuery и ваш Javascript отправляют данные на указанный сервер.

Вот старый Javascript:

$.ajax({
    type: 'POST',
    url: '/Action/Method',
    data: { CustomObject: firstObj, Objects: objsArray },
    //Success/error handlers here
});

Первая проблема заключается в том, что Javascript не сообщает серверу на '/Action/Method', что именно вы отправляете (это двоичный файл, это сочетание параметров или JSON?), Поэтому добавьте строку contentType: 'application/json' будет служить этой цели. Когда вы делаете это, сервер знает, что он должен декодировать JSON ...

Но как бы это ни было сейчас, декодирование завершится сбоем, и будет сгенерировано исключение ("Invalid JSON primitive"), прежде чем код даже войдет в ваш метод (тогда MVC обрабатывает декодирование и связывание). В приведенном выше вызове AJAX я строил новый объект JSON в опциях $.ajax, но отправляемый JSON не прошел бы валидатор JSON (Джеймс Кибурц упоминает отличный валидатор JSON: JSONLint Validator ) , Вместо этого создайте объект JSON перед вызовом $.ajax и зафиксируйте объект так, чтобы он имел правильный формат JSON. В целом вот как должен выглядеть вызов AJAX:

var dataObj = { CustomObject: firstObj, Objects: objsArray };

$.ajax({
    type: 'POST',
    url: '/Action/Method',
    contentType: 'application/json',
    data: JSON.stringify(dataObj),
    //Success/error handlers here
});
3 голосов
/ 19 марта 2012

Изменить public IEnumerable<CustomObject2> Objects { get; set; } на List<CustomObject2>

Связыватель модели не знает, как создать экземпляр интерфейса IEnumerable, ему нужно что-то более конкретное.

Вам также необходимоизмените это:

data: { CustomObject: firstObj, Objects: objsArray }

на

data: { model: { CustomObject: firstObj, Objects: objsArray } }

Часть model соответствует имени параметра в вашем действии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...