views:

23

answers:

2

I've got the following routing in my application...

public static void RegisterRoutes(RouteCollection routes)
{
  routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

  routes.MapRoute(
    "Branding",
    "foo/bar.css",
    new { controller = "DynamicContent", action = "CSS" }
  );

  routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Account", action = "Index", id = UrlParameter.Optional }
  );
}

I'm using Martijn Boland's paging mechanism and it eventually makes the following call:

var virtualPathData = 
  RouteTable.Routes.GetVirtualPath(this.viewContext.RequestContext, pageLinkValueDictionary);

I've verified that my controller and action in RequestContext are valid. But once this call is made, virtualPathData references the URL for foo/bar.css. I have verified that URLs map to the correct controller/action. If I comment out the route above leaving the default, virtualPathData's URL corresponds to the right controller/action.

I've also tried the following line and I have the same result.

//var virtualPathData = 
  RouteTable.Routes.GetVirtualPathForArea(this.viewContext.RequestContext, pageLinkValueDictionary);

Can anyone help me figure out what I'm doing wrong?

A: 

I'm still not exactly sure why I was seeing the behavior above, so if anyone wants to chime in with their ideas feel free.

That said, if someone else hits the same problem, I was able to overcome it by reversing the route order with the more ambiguous default route being added first with a NotEqual constraint to ensure that the DynamicContent route was hit as needed.

routes.MapRoute(
  "Default",
  "{controller}/{action}/{id}",
  new { controller = "Account", action = "Index", id = UrlParameter.Optional },
  new { controller = new NotEqual("DynamicContent") }
);

routes.MapRoute(
  "Branding",
  "foo/bar.css",
  new { controller = "DynamicContent", action = "CSS" }
);

For those who are wondering what NotEqual is, I found it on a blog.

public class NotEqual : IRouteConstraint
{
  private string _match = string.Empty;

  public NotEqual(string match)
  {
    _match = match;
  }

  public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
  {
    return String.Compare(values[parameterName].ToString(), _match, true) != 0; 
  }
}

I'm certainly up for hearing about better ways of doing this OR why my original code wasn't completely working.

Mayo
+1  A: 

Unfortunately, I think the logic for generating URLs doesn't handle static URLs very well. I believe one thing you can do is:

routes.MapRoute( "Branding", "{controller}/bar.css", new { controller = "DynamicContent", action = "CSS" }, new {controller="foo"} );

Try that out.

Haacked
Thanks Phil, it works and is much cleaner than my proposal (which in retrospect is much like a double-negative) - I appreciate it!
Mayo