2014-09-10 5 views
1

Мое требование, чтобы быть в состоянии принять следующие комбинацииДинамически Создание маршрута Параметры в ASP.Net MVC

{Part1}/{Controller}/{Action} 

{Part1}/{Part2}/{Controller}/{Action} 

{Part1}/{Part2}/{Part3}/{Controller}/{Action} 

и передать их в контроллеры и методы, которые преобразовывают Части 1 до 3 в ID, который используется по всей системе. Схема:

string id = part1 + "-" + part2 + "-" + part3 

Трассы организованы таким образом, чтобы создать видимость структуры папок и контроллеры/действия, что доступно для тех, «папки».

Я хотел бы придумать способ сделать это, придерживаясь DRY.

Я думаю, возможно, это действие фильтра (который я буду применять повсеместно), что создает новый идентификатор записи в RouteValueDictionary, принимая значения от присутствия частей 1 до 3.

ли это правильный подход или есть лучшее решение?

спасибо.

ответ

1

Вот идея.

Создать некоторые маршруты

public static void RegisterRoutes(RouteCollection routes) 
{ 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

    routes.MapRoute(
     name: "Special", 
     url: "{part1}/{controller}/{action}" 
     ); 

    routes.MapRoute(
     name: "Special2", 
     url: "{part1}/{part2}/{controller}/{action}" 
     ); 

    routes.MapRoute(
     name: "Special3", 
     url: "{part1}/{part2}/{part3}/{controller}/{action}" 
     ); 

    routes.MapRoute(
     name: "Default", 
     url: "{controller}/{action}", 
     defaults: new { controller = "Home", action = "Index" } 
     ); 
} 

Пример модели

[ModelBinder(typeof(SpecialModelBinder))] 
public class SpecialModel 
{ 
    public string id { get; set; } 
} 

Модель Связующее

public class SpecialModelBinder : DefaultModelBinder 
{ 
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor) 
    { 
     SpecialModel model = (SpecialModel)bindingContext.Model; 
     model.id = string.Join("-", controllerContext.RouteData.Values 
      .Where(x => new string[] { "part1", "part2", "part3" }.Contains(x.Key)) 
      .Select(x => x.Value) 
      ); 
     bindingContext.ModelMetadata.Model = model; 
    } 
} 

Пример Контроллер

public class ManageController : Controller 
{ 
    public ActionResult Edit(SpecialModel model) 
    { 
     return View(); 
    } 
} 

Образцы:

http://www.example.com/style1/Manage/Edit

@Model.Id == "style1" 

http://www.example.com/style1/red/Manage/Edit

@Model.Id == "style1-red" 

http://www.example.com/style1/red/16/Manage/Edit

@Model.Id == "style1-red-16" 
+0

Спасибо. Я согласен, что ModelBinder - лучшее место, чтобы поставить эту логику. Единственный недостаток, который я вижу, заключается в том, что если я использую id в нескольких классах (как в случае с CategoryId или FolderId), все они должны наследоваться от SpecialModel. Правильно? Есть ли способ закодировать это так, чтобы он работал для ЛЮБОГО класса с полем «id»? –

+0

Вы можете изменить привязку модели по умолчанию к своему собственному, а затем изменить код, чтобы он проверял модель для поля «id», а затем приложил все усилия, чтобы заполнить ее. Вы можете изменить стандартное связывание модели с помощью ModelBinders.Binders.DefaultBinder = new SpecialModelBinder(); '; введите его в 'Startup.cs' или' Global.asax'. –

Смежные вопросы