Tricky Asp.net MVC URL Rewriting

I am working on an asp.net mvc application and I wanted to make the user’s main page (profile) be http://www.domain.com/username.  This is a problem because the routing engine in MVC treats the first item after the domain as a controller.  Ofcourse I could do a {*catchall} and do my own parsing but why re-invent the wheel – plus I suck at regular expression.  What I ended up doing is registering all the routes manually.  So if I wanted to go to /message/create, I would register a route like this:

routes.Add(
    new Route("Message/Create", new MvcRouteHandler())
        {
            Defaults = new RouteValueDictionary(new
                                                    {
                                                        controller = "Message",
                                                        action = "Create"
                                                    })
        }
    );

So far so good, nothing earth shattering.  So I basically did this for all my routes and the last route, I added was:

routes.Add(
    new Route("{*username}", new MvcRouteHandler())
       {
           Constraints = new RouteValueDictionary(new {username = "^(?!content/).*"}),
           Defaults = new RouteValueDictionary(new {Controller = "User", action = "View"})
       });

This basically will catch any route that has not been defined before it and will treat it as a username so /eibrahim would go to the view action on the user’s controller.  Also, note that I added a constraint to prevent the catch-all route from catching any url in the content subfolder.  Important: All your scripts, images, css files and so on have to be in the content folder otherwise they will be handled by the catch-all route and not be accessible to your application.

The signature for the view action look like this:

public void View(string username, int? page)
{

}

Now the tricky part is that you want to make sure that your users don’t signup with a username matching the controller.  So if a user decided to register with the username “message”, he will never be able to go to his profile at /message because it will be handled by the generic message route “message/{action}”.  A quick workaround is to prevent the user from registering with those names.  In my signup process I call a method to check if the selected username is valid.  The validation process loops through all the routes and makes sure the username doesn’t match any controller or action.  It works out pretty well so far.

foreach (Route route in RouteTable.Routes)
{
    if (username == route.Defaults["controller"].ToString().ToLower())
        return false;
    if (username == route.Defaults["action"].ToString().ToLower())
        return false;
}

I don’t know if this is the best solution, so if you know of a better way to do it, let me know.

Advertisements

0 thoughts on “Tricky Asp.net MVC URL Rewriting

  1. I’ve done exactly this for a project. It isnt ideal in that if you have a live system, and you subsequently need to add controllers, you need to check that *existing* users havent already used that controller name.

    Like

  2. I’ve done exactly this for a project. It isnt ideal in that if you have a live system, and you subsequently need to add controllers, you need to check that *existing* users havent already used that controller name.

    Like

  3. @Nik, you are absolutely right which is why I force user names to be 4 characters or longer. This way, worst-case-scenario, I can create a 3 letter controller. Not ideal, but a workaround.

    Like

  4. @Nik, you are absolutely right which is why I force user names to be 4 characters or longer. This way, worst-case-scenario, I can create a 3 letter controller. Not ideal, but a workaround.

    Like

  5. Have you thought about what happens if you decide to create a controller which happens to be the same as a user's name?!I'm not sure this is a very future-proof way of working…

    Like

    • You are absolutely right but I have worked around that by forcing users touse usernames with 6 or more characters and I also keep track of a list ofbanned usernames in the config file e.g. administrator, account, etc…It is not perfect but it works otherwise, you will be stuck with URLs thatlook like /user/eibrahim instead of just /eibrahim

      Like

  6. You are absolutely right but I have worked around that by forcing users touse usernames with 6 or more characters and I also keep track of a list ofbanned usernames in the config file e.g. administrator, account, etc…It is not perfect but it works otherwise, you will be stuck with URLs thatlook like /user/eibrahim instead of just /eibrahim

    Like

  7. You are absolutely right but I have worked around that by forcing users touse usernames with 6 or more characters and I also keep track of a list ofbanned usernames in the config file e.g. administrator, account, etc…It is not perfect but it works otherwise, you will be stuck with URLs thatlook like /user/eibrahim instead of just /eibrahim

    Like

  8. Pingback: MVC URL Rewriting - Baka.Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s