13

我需要使用以下网址实现一个 MVC 站点:

  • 类别1/产品/1/wiki
  • 类别1/产品/2/wiki
  • 类别1/子类别2/产品/3/wiki
  • 类别1/子类别2/子类别3/product/4/wiki
  • 等等等等

其中匹配标准是 url 以“wiki”结尾。

不幸的是,下面的包罗万象仅适用于网址的最后一部分:

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

我没有时间浏览 MVC 可扩展性选项,所以我想知道实现此功能的可能选择是什么?任何示例/示例都会很棒!

4

1 回答 1

15

正如您所提到的,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 参数。

于 2009-07-10T04:32:27.207 回答