#asp.net-mvc #modelbinders
#asp.net-mvc #modelbinders
Вопрос:
У меня есть модель с коллекцией
public class Model
{
IEnumerable<ModelPart> Parts {get;set;}
}
public class Parts
{
public string Prop1 {get;set;}
public string Prop2 {get;set;}
}
Но ввод в URL довольно неприятный.
Она имеет такую форму
dhxGridObj_d3BIc6JfDidc_1_0=amp;dhxGridObj_d3BIc6JfDidc_1_1=ssssamp;dhxGridObj_d3BIc6JfDidc_1_2=sssssamp; dhxGridObj_d3BIc6JfDidc_2_0=amp; dhxGridObj_d3BIc6JfDidc_2_1=ааааа и dhxGridObj_d3BIc6JfDidc_2_2=ааааа
Она состоит из трех частей, разделенных символом подчеркивания
dhxGridObj_d3BIc6JfDidc_2_1
- Некоторый идентификатор
dhxGridObj_d3BIc6JfDidc
- Идентификатор строки
2
- Идентификатор ячейки
1
Мне интересно, каким был бы наилучший способ привязать это к моей модели.
Я думал о переименовании этого dhxGridObj_d3BIc6JfDidc_2_1
в model[2].Prop1
Где было бы лучшее место для этого?
Ответ №1:
О да, это чертовски уродливая строка запроса. Пользовательская привязка модели — это способ разобрать это чудовище, пока вы не найдете реальное решение этой проблемы, которое, конечно, исправляет систему, отправляющую это дерьмо, в соответствии с синтаксисом привязки модели по умолчанию.
И вот пример некоторого исходного кода, который может направить вас на правильный путь:
public class MyModelBinder : DefaultModelBinder
{
private const string Prefix = "dhxGridObj_d3BIc6JfDidc";
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var model = base.BindModel(controllerContext, bindingContext) as Model;
var request = controllerContext.HttpContext.Request;
model.Parts = request
.Params
.Keys
.OfType<string>()
.Select(key => Regex.Match(key, Prefix "_([0-9] )_([0-9] )"))
.Where(x => x.Success)
.Select(x => new
{
Row = x.Groups[1].Value,
Col = x.Groups[2].Value
})
.GroupBy(x => x.Row)
.Select(x => new Parts
{
Prop1 = request[string.Format("{0}_{1}_{2}", Prefix, x.Key, x.ElementAt(0).Col)],
Prop2 = request[string.Format("{0}_{1}_{2}", Prefix, x.Key, x.ElementAt(1).Col)],
});
return model;
}
}
которая будет зарегистрирована в Application_Start
:
ModelBinders.Binders.Add(typeof(Model), new MyModelBinder());
Комментарии:
1. Забыл упомянуть, что в классе Parts также выполняется некоторая проверка. Я взглянул на класс defaultmodelbinder. Есть несколько методов для переопределения. Не могли бы вы дать подсказку, какой из них был бы лучшим для этого?
2. @user256034, вы производите от
DefaultModelBinder
и переопределяетеBindModel
метод, в котором вы выполняете логический анализ этих уродливых параметров строки запроса и привязываете их к соответствующим значениям свойств.3. Вау, это потрясающе. Работает как шарм. Но я предполагаю, что я должен выполнить проверку самостоятельно, не так ли?
4. @user256034, какой тип проверки вам нужен? Вы могли бы украсить свойства вашей модели необходимыми атрибутами.
5. Да, я имел в виду примечания к данным. У меня есть некоторые атрибуты для некоторых свойств класса Parts. Но я не вижу места, где должна происходить проверка.
Ответ №2:
Вы не должны использовать параметры строки запроса в URL вашего приложения MVC. лучшим для этого являются URL-маршруты. вы можете найти хорошую статью о маршрутах в MVC здесь :
http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx
Комментарии:
1. но это большая дыра в приложении MVC.