Asp.Net MVC 4 автоматически связывает модель из массива объектов в форме post
Я построил массив объектов в JavaScript и хочу отправить их обратно на сервер через Ajax (Im с помощью jQuery)
Массив объектов JavaScript выглядит следующим образом:
var columns = [
{ name: 'col 1', source: 'whatever', hidden: false, width: 50 },
...
];
Я отправлю его обратно следующим образом:
$.post('/MyController/MyAction', { 'columns': columns });
На действие контроллера Im в настоящее время получает это:

У меня есть объект c# под названием JqColumn, в который я хочу привязать сообщение, он выглядит так:
public class JqGridColumn
{
public string name;
public string source;
public int width;
public bool hidden;
}
Поэтому я подумал, что Добавление параметра в действие контроллера Тип JqGridColumn[] columns автоматически связывает опубликованные данные, но это не так (он генерирует массив с правильным количеством элементов, но каждый элемент в массиве имеет пустые значения)
Может ли кто-нибудь сказать мне, что я делаю не так? Спасибо!
Обновить
В настоящее время я вручную связываю элементы в моем действии контроллера следующим образом:
public void ColumnChooser(JqGridColumn[] columns)
{
for (int i = 0; i < columns.Length; i++)
{
columns[i].hidden = bool.Parse(Request.Form["columns[" + i + "][hidden]"]);
columns[i].width = int.Parse(Request.Form["columns[" + i + "][width]"]);
columns[i].name = Request.Form["columns[" + i + "][name]"];
columns[i].source = Request.Form["columns[" + i + "][source]"];
}
return;
}
...что прекрасно работает, но я действительно хотел бы знать, как это сделать с помощью .Net MVC (правильно)!
3 ответов:
Поскольку вы не зарегистрировали конкретный
ModelBinderдля типаJqGridColumn, будет использоватьсяDefaultModelBinder. Но:
Он не будет связывать поля, только общие свойства.
Ожидаемый формат привязки массива -
columns[0].name, в то время как вы фактически публикуетеcolumns[0][name].Проблема может быть решена легко, если вы просто отправите свой
columnsв формате JSON вместо пар имя-значение :$.ajax({ url: '/MyController/MyAction', method: 'POST', contentType: 'application/json', data: JSON.stringify({ columns: columns }) });Тем не менее, если вы не хотите менять свой класс, вы можете зарегистрировать
ModelBinderспецифичный дляJqGridColumnи заставить его работать даже с полями и текущей сериализацией jQuery:public class JqGridColumnBinder : DefaultModelBinder { protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) { string name = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + "[name]").AttemptedValue; string source = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + "[source]").AttemptedValue; int width = (int)bindingContext.ValueProvider.GetValue(bindingContext.ModelName + "[width]").ConvertTo(typeof(int)); bool hidden = (bool)bindingContext.ValueProvider.GetValue(bindingContext.ModelName + "[hidden]").ConvertTo(typeof(bool)); return new JqGridColumn { name = name, source = source, width = width, hidden = hidden }; } }Затем зарегистрируйте его в App_Start/ModelBindingConfig.cs :
binders.Add(typeof(JqGridColumn), new JqGridColumnBinder());
Это потому, что ваш объект JqGridColumn нуждается в свойствах, а не в полях. смотрите этот вопрос Для справки:
Попробуйте отправить назад с традиционной настройкой: true и тип данных: json
$.ajax({ url: '/MyController/MyAction', method: 'POST', traditional: true, dataType: json data: columns , sucess: function () { alert('Success'); } });
Comments