For anybody interesting in having ruby on rails style routes; or follow a lowercase URL pattern (mysite.com/member/profile/goneale) which most web 2.0 sites seem to be following, check out the below code cited and enhanced from this article (http://www.makiwa.com/index.php/2008/05/31/lowercase-mvc-route-urls/).
Firstly you will need a RouteExtensions.cs file, or named anything you like with the following (compatible as at ASP.NET MVC RC1):
using System;
using System.Web.Mvc;
using System.Web.Routing;
namespace MyMvcApplication.App.Helpers
{
public class LowercaseRoute : System.Web.Routing.Route
{
public LowercaseRoute(string url, IRouteHandler routeHandler)
: base(url, routeHandler) { }
public LowercaseRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
: base(url, defaults, routeHandler) { }
public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler)
: base(url, defaults, constraints, routeHandler) { }
public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler)
: base(url, defaults, constraints, dataTokens, routeHandler) { }
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
VirtualPathData path = base.GetVirtualPath(requestContext, values);
if (path != null)
path.VirtualPath = path.VirtualPath.ToLowerInvariant();
return path;
}
}
public static class RouteCollectionExtensions
{
public static void MapRouteLowercase(this RouteCollection routes, string name, string url, object defaults)
{
routes.MapRouteLowercase(name, url, defaults, null);
}
public static void MapRouteLowercase(this RouteCollection routes, string name, string url, object defaults, object constraints)
{
if (routes == null)
throw new ArgumentNullException("routes");
if (url == null)
throw new ArgumentNullException("url");
var route = new LowercaseRoute(url, new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints)
};
if (String.IsNullOrEmpty(name))
routes.Add(route);
else
routes.Add(name, route);
}
}
}
Then a using reference in your Global.asax.cs file to the above class, and you’re all set to create a lowercase route.
You can see a below example of a lowercase route and anytime this route is called your URL will be lowercased.
routes.MapRouteLowercase(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {controller = "Home", action = "index", id = ""} // Parameter defaults
);
and optionally if you are interested in converting any incoming URL’s to lowercase (manually typed by the user or called links) you can use this in your Application_BeginRequest() method (Remember, this is not needed for lowercase routes themselves, the code above will handle that):
protected void Application_BeginRequest(Object sender, EventArgs e)
{
// If upper case letters are found in the URL, redirect to lower case URL.
// Was receiving undesirable results here as my QueryString was also being converted to lowercase.
// You may want this, but I did not.
//if (Regex.IsMatch(HttpContext.Current.Request.Url.ToString(), @"[A-Z]") == true)
//{
// string LowercaseURL = HttpContext.Current.Request.Url.ToString().ToLower();
// Response.Clear();
// Response.Status = "301 Moved Permanently";
// Response.AddHeader("Location", LowercaseURL);
// Response.End();
//}
// If upper case letters are found in the URL, redirect to lower case URL (keep querystring the same).
string lowercaseURL = (Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath);
if (Regex.IsMatch(lowercaseURL, @"[A-Z]"))
{
lowercaseURL = lowercaseURL.ToLower() + HttpContext.Current.Request.Url.Query;
Response.Clear();
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location", lowercaseURL);
Response.End();
}
}
13 Comments
Hi Graham. This may be a really lame question, but what plugin, etc are you using here to display your code? I will be setting up a wordpress.com coding blog in the near future and would like this functionality. Feel free to email me the answer and then delete this comment.
Thanks!
Hi Terry,
That’s fine. I might as well keep your comment, makes my blog look busy
It is one built in to wordpress I found. Simply encapsulate your code in tags like this:
[sourcecode language='language-here']
hello!
[/sourcecode]
More info and languages that can be used can be found here:
http://support.wordpress.com/code/5/
First of all congratulation for such a great site. I learned a lot reading here today. I will make sure i visit this site more often so I can learn more.
Make your long Urls shorter – Free Url redirection – Hide your affilate URLS
Thanks Josh!
Really glad you’ve found it useful. I try to update it regularly, so feel free to drop by anytime. I also have an RSS feed you can use any feed reader to subscribe to if you like @ http://goneale.wordpress.com/feed.
I’ll actually make a hyperlink for that right now!
if (Regex.IsMatch(lowercaseURL, @”[A-Z]“) == true)
this is nor correct i believe. Cause we will never go into the if statement even if url is not lowercase. We are using our lowercaseurl for checking uppercase characters which will never be true.
Something like this works fine:
if (Regex.IsMatch(HttpContext.Current.Request.Url.AbsoluteUri, @”[A-Z]“) == true)
@Celik: You know what Celik, this code needs to be re-worked, what happened was I originally was running with this RegEx and a different if statement (I believe from here http://stackoverflow.com/questions/170900/how-can-i-avoid-duplicate-content-in-asp-net-mvc-due-to-case-insensitive-urls-and), but ran in to issues with my QueryString being converted to lowercase also, which was undesirable. So what I do now, for all requests is ToLower() the Url and append the QueryString in original casing.
The old code was:
// If upper case letters are found in the URL, redirect to lower case URL.
if (Regex.IsMatch(HttpContext.Current.Request.Url.ToString(), @”[A-Z]“) == true)
{
string LowercaseURL = HttpContext.Current.Request.Url.ToString().ToLower();
Response.Clear();
Response.Status = “301 Moved Permanently”;
Response.AddHeader(“Location”, LowercaseURL);
Response.End();
}
You can see there that the entire URI including QS is converted to lower, so if you have a URL like localhost/my/page/list/2?CategoryID=40 you may want to keep CategoryID in this casing.
(This has been done!)
I can’t recall where I needed my QS to remain in correct casing but it was a problem at the time.
I will update the code sample with an actually useful Global.asax
Thanks Graham for the code. It helped me resolve the case-insensitive duplicate content issue. But it caused another problem. When you visit the website without any page mentioned. It will show the name of the landing page in the URL. I tried to remove that landing page from the URL before redirecting, but it didn’t work. Please see if there is any fix for it.
Great article, thank you so much
Thanks for the solution, but this doesn’t work for Area’s. I found a solution for area’s here http://www.google.com/codesearch/p?hl=en#RvvkzXvPN5c/src/BetaBlog/Web/Routing/RouteCollectionExtensions.cs&q=RouteCollectionExtensions%20package:http://betablog\.googlecode\.com&sa=N&cd=1&ct=rc
Your solution is not working with MVC Areas like admin. Any solution to that?
Any idea how to do this when using Areas?
routes.MapRouteLowercase(
“Default”, // Route name
“{controller}/{action}/{id}”, // URL with parameters
new {controller = “Home”, action = “index”, id = “”} // Parameter defaults
);
I have searched all and have not found anything of any use for doing this with Areas. Any help would be appreciated.
Hi i hava tried implementing this code for url rewriting to lower case but it is not working
protected void Application_BeginRequest(object sender, EventArgs e)
{
string lowercaseURL = (Request.Url.Scheme + “://” + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath);
if(Regex.IsMatch(lowercaseURL,@”[A-Z]“))
{
lowercaseURL = lowercaseURL.ToLower() + HttpContext.Current.Request.Url.Query;
Response.Clear();
Response.Status = “301 Moved Permanently”;
Response.AddHeader(“Location”, lowercaseURL);
Response.End();
}
}
it is working well in visual studio on my computer but when i host it on my server in godaddy its not working . can any one help me
example
google is considering urls
http://www.mydomain.com/Hyderabad.aspx and http://www.mydomain.com/hyderabad.aspx as two different pages
please help me
Yeah .. i am trying to find a way to figure out how to do this in areas as well..
here is my question
http://stackoverflow.com/questions/7368749/net-mvc3-lowercase-route-urls-in-areas
5 Trackbacks/Pingbacks
[...] post is based off 2 other blog posts I found which helped me come up with my solution with some slight modifications on their [...]
[...] Use Custom Routing Extensions I like all my URLs to be lower case, but I don’t want to change my controller and action methods to be lower case. The use of a RoutingCollection extension method easily solves this. Found this nifty extension method at: http://goneale.com/2008/12/19/lowercase-route-urls-in-aspnet-mvc/ [...]
[...] Iam starting to create lowercase urls on my site. I have used this code: http://goneale.com/2008/12/19/lowercase-route-urls-in-aspnet-mvc/ [...]
[...] and change all redicecciones and links to lowercase. also applies the class “lowercase route urls in aspnet mvc” and works perfectly.The problem I had to modify the virtual directory in IIS, delete virtual [...]
[...] Use Custom Routing Extensions I like all my URLs to be lower case, but I don’t want to change my controller and action methods to be lower case. The use of a RoutingCollection extension method easily solves this. Found this nifty extension method at:http://goneale.com/2008/12/19/lowercase-route-urls-in-aspnet-mvc/ [...]
Post a Comment