我有一个使用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); } }
在注册所有路由后,我将在一个简单的循环中分配装饰器.
var routes = RouteTable.Routes; for (var i = 0; i < routes.Count; i++) { routes[i] = new RouteDecorator(routes[i]); }
如何在不破坏路线和区域的情况下安全地插入装饰器?
我有一个可用的复制解决方案to download here.在复制中,路线装饰器被注释掉了.将其注释回来将会中断路由,并且第一个虚拟区域的路由数据将匹配通常仅正确匹配相应命名空间的链接.
我认为这取决于区域使用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; }
[编辑 – 2009-11-12]
我相信以下将解决这个问题,因为装饰器似乎最终不止一次包装路线:装饰者的附加财产:
public RouteBase InnerRoute { get { return _route; } }
接口实现:
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; } }
精彩评论