ASP.net MVC пользовательский обработчик маршрута / ограничение - PullRequest
13 голосов
/ 10 июля 2009

Мне нужно реализовать сайт MVC с URL-адресами ниже:

  • category1 / продукт / 1 / вики
  • category1 / продукт / 2 / вики
  • category1 / суб-category2 / продукта / 3 / вики
  • категория1 / суб-категория2 / суб-category3 / продукта / 4 / вики
  • и т.д.. и т.д.

где критерием совпадения является то, что URL оканчивается на "wiki".

К сожалению, приведенный ниже универсальный метод работает только в последней части URL:

routes.MapRoute("page1", // Route name
                "{*path}/wiki", // URL with parameters
                new { controller = "Wiki", action = "page", version = "" } // Parameter defaults

У меня не было времени, чтобы просмотреть параметры расширяемости MVC, поэтому мне было интересно, каковы возможные варианты реализации этого? Любой образец / пример был бы просто фантастическим!

1 Ответ

15 голосов
/ 10 июля 2009

Как вы упомянули, параметр catch-all может появляться только в конце маршрута - код, который вы опубликовали, выдаст ошибку времени выполнения и даст вам желтый экран смерти, если вы даже попытаетесь запустить применение.

Существует несколько точек расширения для создания пользовательских сценариев маршрутизации. Это - Route, RouteBase и IRouteHandler.

Вы можете создать сгенерированный список маршрутов для обработки путем расширения RouteBase. Как правило, вы должны следовать шаблону наличия конструктора, который получает ресурс (имя контроллера), а затем назначать ему список маршрутов, за которые он отвечал, и затем отображать его в вашем global.asax. Вот пример кода, из которого вы можете построить:

public class MyRoute : RouteBase
{
    private List<Route> _routes = new List<Route>();

    public MyRoute(string resource)
    {
        // make a Resource property, not shown in this example
        this.Resource = resource;

        // Generate all your routes here
        _routes.Add(
            new Route("some/url/{param1}",
            new McvRouteHandler {
                Defaults = new RouteValueDictionary(new {
                    controller = resource,
                    action = actionName
                }),
            Constraints = new RouteValueDictionary()
        );
        _routes.Add(...); // another new route   
    }

    public override RouteData GetRouteData(HttpContextBase context)
    {
        foreach (var route in _routes)
        {
            var data = route.GetRouteData(context);
            if (data != null)
            { 
                return data;
            }
        }
        return null;
    }

    public override VirtualPathData GetVirtualPath(RequestContext context, RouteValueDictionary rvd)
    {
        foreach (var route in _routes)
        {
            var path = route.GetVirtualPath(context, rvd);
            if (path != null)
            { 
                return path;
            }
        }
        return null;
    }
}

Чтобы использовать свой класс маршрутизации, выполните routes.Add(new MyRoute("page1")); в вашем Global.asax.

Если вам нужен еще больший контроль, вы можете реализовать IRouteHandler и вместо создания MvcRouteHandlers () для ваших маршрутов, как показано в примере выше, использовать свой собственный IRouteHandler. Это позволит вам переопределить логику выбора контроллера из данных запроса.

Весь фреймворк чрезвычайно расширяем, но вам нужно немало учиться, чтобы сделать это правильно. Я бы порекомендовал просто изменить ваши URL-адреса, если это возможно, чтобы использовать параметр catch-all, если вы можете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...