views:

12

answers:

1

I have a route defined last in my ASP.Net MVC 2 app that will map old urls that are no longer used to the appropriate new urls to be redirected to. This route returns the action and controller that is responsible for actually performing the redirect and it also returns a url to the controller action which is the url to redirect to. Since the route is responsible for generating the new url to redirect to, it is calling the router to get the appropriate urls. This has worked just fine with .Net 3.5, but when I upgraded to .Net 4, the GetVirtualPath method throws a System.Threading.LockRecursionException: "Recursive read lock acquisitions not allowed in this mode.". The following code resolves the problem but is pretty ugly:

public static string GetActionUrl(HttpContextBase context, string routeName, object routeValues)
    {
        RequestContext requestContext = new RequestContext(context, new RouteData());
        VirtualPathData vp = null;

        try
        {
            vp = _Routes.GetVirtualPath(requestContext, routeName, new RouteValueDictionary(routeValues));
        }
        catch (System.Threading.LockRecursionException)
        {
            var tmpRoutes = new RouteCollection();
            Router.RegisterRoutes(tmpRoutes);
            vp = tmpRoutes.GetVirtualPath(requestContext, routeName, new RouteValueDictionary(routeValues));
        }

        if (vp == null)
            throw new Exception(String.Format("Could not find named route {0}", routeName));

        return vp.VirtualPath;
    }

Does anybody know what changes in .Net 4 might have caused this error? Also, is calling a route from another route's GetRouteData method just bad practice and something I should not be doing at all?

+1  A: 

As you figured out, it is not supported to call a route in the global route table from within another route in the global route table.

The global route table is a thread-safe collection to enable multiple readers or a single router. Unfortunately the code you have was never supported, even in .NET 3.5, though in some scenarios it may have coincidentally worked.

As a general note, routes should function independent of one another, so I'm not sure what your scenario is here.

Eilon