3

My ASP.NET MVC site allows users to register and give themselves user names, which will be unique and allow others to browse their pages with a clean URL that includes their name, like Twitter, Facebook, LinkedIn etc. do.

For example:

  • mysite.com/michael.guthrie
  • mysite.com/john
  • mysite.com/john/images
  • mysite.com/john/blog

etc.

The problem is that the first URL segment might be used for other "regular" controllers/actions, like:

  • mysite.com/about
  • mysite.com/register

So basically I seek for a routing scheme that says something like: If the first URL segment is a known controller, treat it as a controller (and parse the relevant action and parameters as usual), but if not - treat it as a user name, and pass it to a dedicated controller+action which will parse it and continue accordingly.

I don't want a solution that will enforce me to add routes for every specific controller that I have, such that after the routing module will go over all of them and won't find a match, it will get to the last one which defines a route for this special user name segment. The reason is primarily maintenance (I must remember to add a route every time I code a new controller, for example.)

I assume I can implement my own MvcRouteHandler / IRouteHandler but I feel there must be simpler solution that won't have me tweak MVC's out-of-the-box routing mechanism.

Note: I've read How to achieve nice litle USER page url like facebook or twitter? and it doesn't answer my question, it's just says that there is a URL rewriting module.

Do you know any good, elegant, clean way to achieve that?

Community
  • 1
  • 1
Ofer Zelig
  • 17,068
  • 9
  • 59
  • 93

2 Answers2

2

You should have your first route be your Usesr route, with a route constraint along the lines of what I described in this answer: MVC routing question.

If your route is in the form {username}/{controller}/{id}, this route should cover all contingencies.

Community
  • 1
  • 1
counsellorben
  • 10,924
  • 3
  • 40
  • 38
  • 2
    Your answer is a big step towards what I need. The main problem is that every route analyzing is a "whitelisting" which involves an expensive database hit. I believe that the right solution should be "blacklisting" - i.e. if the route does not match any known controller/action in my app, then I assume it is a username and proceed accordingly. The question is how to elegantly know what are all my controllers and actions without the need to add a route entry every time I add controllers or so. – Ofer Zelig Aug 28 '11 at 14:12
  • I've got some interesting idea which is a twist over the last link you've sent. When I'll implement it I will post it here. In the mean time I set your answer as accepted - Thank you! – Ofer Zelig Aug 28 '11 at 15:25
  • You could adapt the answer described here: http://stackoverflow.com/questions/790464/accessing-the-list-of-controllers-actions-in-an-asp-net-mvc-application. However, if someone mistypes a controller name, then you will end up in your "Users" route. Also, I think the expense of the reflection to determine the list of all actions and controllers (followed by the need to determine whether the username entered is valid) makes for a solution which is more costly overall. – counsellorben Aug 28 '11 at 15:26
0

in the global.asax file you can map your routes in the registerRoutes() method you can do something like this:

routes.MapRoute(
                "ToonStudenten", // Route name
                "{controller}/{action}/{userID}, // URL with parameters
                new { controller = "Docent", action = "ToonStudenten", userID = UrlParameter.Optional} // Parameter defaults
            );

I believe you can change the way your views look with this mapRouting, not entirely sure how though.. will try and search it up

You may want to take a look at this post: MVC 3 keeping short url

You don't need to set a route for each URL. With a little help from route constraints you can do something like this:

routes.MapRoute(
    "Home", // Route name
    "{action}", // URL with parameters
    new { controller = "Home", action = "Index" }, // Parameter defaults
    new { action = "TaskA|TaskB|TaskC|etc" } //Route constraints
);

routes.MapRoute(
    "Account", // Route name
    "{action}", // URL with parameters
    new { controller = "Account", action = "Logon" }, // Parameter defaults
    new { action = "Logon|Logoff|Profile|FAQs|etc" } //Route constraints
);
Community
  • 1
  • 1