views:

440

answers:

2

I've got a route that looks like this:

routes.MapRoute(
"BlogTags",
"Blog/Tags/{tag}",
new { controller = "Blog", action = "BrowseTag", viewRss = false }
);

And I create a URL using that route like this:

<%= Html.RouteLink(Html.Encode(sortedTags[i].Tag), 
         new { action = "BrowseTag", tag = sortedTags[i].Tag })%>

However, when a tag with a # character (like "C#") is used, the routing engine doesn't escape it, so I get a URL that looks like this:

<a href="/Blog/Tags/C#">C#</a>

What I need is the # escaped so that it looks like this:

<a href="/Blog/Tags/C%23">C#</a>

I tried doing a Url.Encode on the tag before it went into the route, like this:

<%= Html.RouteLink(Html.Encode(sortedTags[i].Tag), 
         new { action = "BrowseTag", tag = Url.Encode(sortedTags[i].Tag) })%>

But that makes the routing engine double escape the # (which causes an ASP.NET crash with a bad request error)):

<a href="/Blog/Tags/C%2523">C#</a>

How can I get the routing engine to escape that # character for me correctly?

Thank you for your help in advance.

+1  A: 

As a very bald solution, I would manually replace "#" with "%23" in the output of RouteLink. Provided you don't use fragments in your urls, it should work.

You could use regular expression to only apply replace to the last part of your url.

Developer Art
If I can't find a cleaner (ie. fragment-supporting, works for everything) solution, I'll totally take your advice.
Daniel Chambers
As an option, look inside the source code of RouteLink. Maybe you can add an overload. I have found that taking the source code of MVC as a basis to add some custom behavior is a great way to get exactly what you want. RedirectToRoute with fragment support was one of them.
Developer Art
A: 

I have a similar SO question relating to "/". While researching that issue I learned that ASP.NET decodes the URL values before they get passed to the MVC framework, and since "#" has special meaning to URLs (just like the "/" I was dealing with) there's a good chance that something in the base routing engine is causing this behavior.

Like Levi mentioned in his comment, one solution is to use ASP.NET 4.0. Another solution would be to write a RouteLink helper that automatically replaces "#" with some marker (like "!MY_HASH_TOKEN!") and then reverse that replacement in your controller (or perhaps via a HttpModule of some sort).

Or, just throw in the towel and pass the tag value as a querystring argument. Not as sexy, but its simple and it works.

Seth Petry-Johnson