asp.net привязка mvc к конкретной модели

#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

  1. Некоторый идентификатор dhxGridObj_d3BIc6JfDidc
  2. Идентификатор строки 2
  3. Идентификатор ячейки 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.