为什么路由装饰器会破坏ASP.NET MVC 2中的路由?

Dan*_*nna 6 asp.net asp.net-mvc routing

我有一个使用MVC 2 Preview 2的Web应用程序,并且在注册了所有路由之后,我需要将每个路径包装在装饰器的下游.问题是,这样做会破坏路由.最终发生的是GetVirtualPath方法将错误地匹配应用程序中的其他区域(我正在使用单项目区域).装饰器是否做任何有用的事并不重要.使用以下passthrough是你需要打破它.

public class RouteDecorator: RouteBase
{
    readonly RouteBase _route;

    public RouteDecorator(RouteBase route)
    {
        _route = route;
    }

    public override RouteData GetRouteData(HttpContextBase context)
    {
        return _route.GetRouteData(context);
    }

    public override VirtualPathData GetVirtualPath(RequestContext context, RouteValueDictionary values)
    {
        return _route.GetVirtualPath(context, values);
    }
}
Run Code Online (Sandbox Code Playgroud)

在注册所有路由后,我将在一个简单的循环中分配装饰器.

var routes = RouteTable.Routes;
for (var i = 0; i < routes.Count; i++)
{
    routes[i] = new RouteDecorator(routes[i]);
}
Run Code Online (Sandbox Code Playgroud)

如何在不破坏路线和区域的情况下安全地插入装饰器?

我有一个可在此处下载的复制解决方案.在复制中,路线装饰器被注释掉.将其注释回来将会中断路由,并且第一个虚拟区域的路由数据将匹配通常仅正确匹配相应命名空间的链接.

Lon*_*eer 5

我认为这取决于区域使用DataTokens字典存储区域/命名空间信息的方式.当您继承自RouteBase时,您可能还需要实现IRouteWithArea接口,因为您没有Route具有的DataTokens.

ActionLink助手似乎间接调用了这个新接口的需要:

public static string GetAreaName(RouteBase route)
{
    IRouteWithArea area = route as IRouteWithArea;
    if (area != null)
    {
        return area.Area;
    }
    Route route2 = route as Route;
    if ((route2 != null) && (route2.DataTokens != null))
    {
        return (route2.DataTokens["area"] as string);
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

[编辑 - 2009-11-12] 我相信以下将解决这个问题,因为装饰器似乎最终包装路线不止一次:

装饰者的附加财产:

  public RouteBase InnerRoute
        {
            get
            {
                return _route;
            }
        }
Run Code Online (Sandbox Code Playgroud)

接口实现:

  public string Area
        {
            get
            {

                RouteBase r = _route;
                while (r is RouteDecorator)
                    r = ((RouteDecorator) r).InnerRoute;
                string s = GetAreaToken(r);
                if (s!= null) return s;
                return null;
            }
        }

        private string GetAreaToken(RouteBase r)
        {
            var route = r as Route;
            if (route != null && route.DataTokens !=null && route.DataTokens.ContainsKey("area"))
            {
                return (route.DataTokens["area"] as string);
            }
            return null;
        }
    }
Run Code Online (Sandbox Code Playgroud)