When adding custom routing constraints to my route parameters I am finding that it is breaking the Url.Action method I use to build my links. If the route constraint is simply a regular expression then the Url.Action method continues to recognize the parameter, however if it is a custom constraint which I define, Url.Action method gives my parameter as a request parameter.
Here is my route definition:
routes.MapRoute(
"Event",
"Events/{strDate}",
new { controller = "Events", action = "Index", strDate = DateTime.Today.ToString("yyyy-MM-dd") },
new { strDate = new IsValidDateConstraint() },
new[] { "MyProject.Controllers" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "MyProject.Controllers" }
);
The IsValidDateConstraint class inherits from IRouteConstraint and returns true or false if the strDate parameter parses correctly to a DateTime object:
public class IsValidDateConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
if (routeDirection == RouteDirection.IncomingRequest)
{
DateTime dt = new DateTime();
if (DateTime.TryParse(values["strDate"].ToString(), out dt))
return true;
}
return false;
}
}
Using the Url.Action method to build URL’s:
@Url.Action("Index", "Events", new { strDate = ViewBag.CurrentDate.AddDays(1).ToString("yyyy-MM-dd") })
The resulting link is: /Events?strDate=2012-08-15
Everything routes correctly if I type in /Events/2012-08-15, it’s just that the Url.Action method is not recognizing that strDate is a parameter defined in my route only when I apply my custom routing constraint. If I comment out the custom routing constraint then the Url.Action method maps the URL correctly.
Any ideas on why the Url.Action is not recognizing my route parameter when I have a custom route constraint defined?
You haven’t shown how your
IsValidDateConstraintlooks like but make sure you are doing a culture invariant parsing for theyyyy-MM-ddformat:Also make sure that this route is placed before the default route:
also
DateTime.Parse(ViewBag.CurrentDate.ToString())looks a wee-bit of a WTFkish code. IfViewBag.CurrentDateis already a DateTime you could directly write:Obviously a much better solution is to use view models:
UPDATE:
Now that you have shown your code the problem comes from the if condition you have put in your constraint:
When using the
Url.Actionhelper this condition is never satisfied. Only when resolving an incoming url. So you will have to remove it if you want this constraint to work with url helpers.