Why do route designers break routing in ASP.NET MVC 2?

I have a web application using MVC 2 Preview 2 and after registering all the routes I need to wrap each route in the decorator further down the chain. The problem is that this interrupts routing. As a result, the GetVirtualPath process will be falsely used for other areas of the application (I use single-project areas). It doesn't matter if the decorator does anything useful or not. Using the following pass-through is all you need to break it.

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); } } 

I assign the decorator to a simple loop after registering all routes.

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

How can I safely insert a decorator without breaking routes and areas?

I have a playback solution to download here . During playback, the route decoder is commented out. By commenting on this, you will break the routing, and the first routing data in the dummy area will correspond to links, which usually will correctly only match the corresponding namespace.

+6
asp.net-mvc routing
source share
2 answers

I think this is about how regions use the DataTokens dictionary to store namespace / namespace information. Since you are inheriting from RouteBase, you probably need to implement the IRouteWithArea interface, since you don't have DataTokens that Route has.

The ActionLink helper seems to indirectly call this, hence the need for this new interface:

 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; } 

[Edit - 2009-11-12] I believe the following fix for the problem, since the decorator seems to complete the route more than once:

Additional properties on the decorator:

  public RouteBase InnerRoute { get { return _route; } } 

Interface Execution:

  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; } } 
+5
source share

What happens if you decorate the Route class instead of RouteBase?

Think of something like this:

 public class RouteDecorator: Route { readonly Route _route; public RouteDecorator(Route 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); } } 

I also recommend checking System.Web.Routing.dll with Reflector, it can give you an idea of ​​what is going on.

And also what happens if you do this:

 var routes = RouteTable.Routes.ToList(); RouteTable.Routes.Clear(); //or, alternatively, if the above doesn't work: //RouteTable.Routes = new RouteCollection(); foreach (var r in routes) { RouteTable.Routes.Add(new RouteDecorator(r)); } 

I really hope this helps.

0
source share

All Articles