2012-03-19 6 views
8

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

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

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 на два отдельных параметра, но это не помогает.

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

ответ

5

Таким образом, решение этой проблемы представляет собой комбинацию из двух или более решений, найденных в другом месте на 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 
}); 
+0

спасибо, это помогло много :)! – Rookian

+0

После того, как часы искали полнофункциональный код, это решило мою проблему! Благодаря!! –

3

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

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

Кроме того, необходимо изменить:

data: { CustomObject: firstObj, Objects: objsArray }

в

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

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

+0

Я играл с этим - 'IEnumerable',' IList', 'list' все те же результаты - список с правильным количеством объектов, не имеют значений. – Mattygabe

+0

Я не согласен со своей второй частью - хотя это может помочь в некоторых случаях, MVC3 достаточно умен, чтобы различить, что данные, которые я передаю, принадлежат моему параметру 'model'. Рабочее решение, описанное выше, не указывает дополнительный слой объекта, чтобы успокоить MVC - он может различить, что я делаю. – Mattygabe