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 (правильно)!

570   3  

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 нуждается в свойствах, а не в полях. смотрите этот вопрос Для справки:

ASP.net привязка MVC-модели исключает поля класса?

Попробуйте отправить назад с традиционной настройкой: true и тип данных: json

$.ajax({
    url: '/MyController/MyAction',
    method: 'POST',
    traditional: true,
    dataType: json
    data: columns ,            
    sucess: function () { alert('Success'); }
});

Comments

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