views:

265

answers:

3

I have an ASP.NET MVC site where I want routes like /{controller}/{id}/{action}/{date}, where "date" is the mm/dd/yyyy portion of a date/time. (I'm dealing with time-dimensioned data, so I need both an ID and a point in time to do most operations)

The route for this is simple:

routes.MapRoute(
    "TimeDimensionedRoute",
    "{controller}/{id}/{action}/{date}",
    new { controller = "Iteration", action = "Index", id = String.Empty, date = String.Empty }
);

This route correctly maps "/Foo/100/Edit/01%2F21%2F2010" to the desired action. Update: this is incorrect. This is NOT routed correctly, I was mistaken. See the related question linked in the accepted answer.

My problem is that when I use Html.ActionLink() to generate a link for this route, it does not URL-encode the date and I end up with invalid URLs such as "/Foo/100/Edit/01/21/2010".

Is there any way to get the routing infrastructure to encode the values for me? It seems wrong that I have to manually URL-encode data that I pass to the HTML helpers.

+3  A: 

I'm guessing that it doesn't automatically url encode it b/c its hard for the html helper to determine if you want to represent a date or if you want to have 3 more fields in the route e.g.

// Here's what you're seeing
/Foo  /100  /Edit  /10/21/2010/
// 4 route values

// But there's know way to know you don't want this
/Foo  /100  /Edit  /10  /21  /2010/
// 6 route values

Maybe you could change your route to be

...
"{controller}/{id}/{action}/{month}/{day}/{year}",
...

That way, it would always work without escaping.

Otherwise, you could do a URL Encoding of the date within the Html.ActionLink(...) call

TJB
I thought about changing the route to accept month/day/year. It's certainly more human readable, but I want my controller actions to take a single DateTime object, not three separate values. I then thought about writing a custom model binder to bridge the gap, but that seemed like a lot of extra work with dubious value. In the end I just wrote a helper that takes the DateTime instance and converts it to "mm-dd-yyyy", which works fine as a route data value.
Seth Petry-Johnson
A: 

You can not use a forward slash in a route value in ASP.NET MVC. Even if it is URL-encoded it wont work.

slash in url

There is only a solution if you use ASP.NET 4.0

Malcolm Frexner
Thanks for the link to the related question. I searched, but didn't find it. However, you state there is a solution in MVC2, but the answers in the linked question only show a workaround for ASP.NET 4.0.
Seth Petry-Johnson
why is this marked as an answer when its obvious it is not? TJB's reply is more of an answer to this, at very least, it is a better way to go.
mare
Sry Seth you are right, the fix is for ASP.NET 4.0 only. I edited my answer.
Malcolm Frexner
@MarkoH: I agree that TJB's answer is helpful as it points out a workaround. However, I accepted this as the answer because I felt that it was a more direct answer to my actual question. It points out that this behavior is coming from a framework-level method call and that there's no easy way to override it in .NET 3.5.
Seth Petry-Johnson
+1  A: 

I don't know if this counts as an answer or not, but I always use yyyy-mm-dd format in URIs. Not because slashes are reserved per the RFC (although that's a good reason) but because it is immune to globalization issues when converting to/from a string. DateTime.Parse() "just works" with this format, even if someone sets the server locale to somewhere in Eastern Europe.

Craig Stuntz
That's a good idea, thanks!
Seth Petry-Johnson