ASP.net MVC自定义路由处理程序/约束

时间:2009-07-10 03:18:03

标签: asp.net-mvc constraints asp.net-mvc-routing

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

  • 类别1 /产物/ 1 /维基
  • 类别1 /产物/ 2 /维基
  • 类别1 /子类别2 /产品/ 3 /维基
  • 类别1 /子类别2 /子类别3 /产品/ 4 /维基
  • 等。等

其中匹配条件是url以“wiki”结尾。

不幸的是,下面的catch-all仅在url的最后部分有效:

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

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

1 个答案:

答案 0 :(得分: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;
    }
}

要使用路由类,请在Global.asax中执行routes.Add(new MyRoute("page1"));

如果你需要更多控制,你可以实现一个IRouteHandler,而不是为你的路由创建MvcRouteHandlers(),如上例所示,使用你自己的IRouteHandler。这将允许您覆盖从请求数据中选择控制器的逻辑。

整个框架非常易于扩展,但为了正确完成,您需要学习很多东西。我建议如果可能的话,只需重新安排你的URL就可以利用catch-all参数。