obliojoe
obliojoe

Reputation: 482

Dynamically generating many routes in ASP.NET MVC... is this a totally bad idea?

Here is my dilemma. I have a collection of entities that I want to use to define as the starting point for a set of routes. For example, I want to give all of the users in my site their own "subsites" of the form mydomain.com/username, and then hang all of the UserController actions off of that.

Here is a rough example of what I am doing:

I have a "UserController", with action methods like "Index", "Profile" and "Bio".

public ActionResult Profile( int UserID )
{
    User u = User.SingleOrDefault(u => u.UserID == UserID);
    return View(u);
}

In RegisterRoutes() method, I do this:

foreach (User user in User.Find(u => u.Active == true))
{
    routes.MapRoute(
         "",
         user.UserName + "/{action}",
         new { controller="User", action="Index", UserID=user.UserID }
     );
}

This works, and it works exactly as I want it to:

domain.com/[username]/Profile
domain.com/[username]/Bio

are now valid, working routes, and they can take in the UserID as the method parameter in the controller because each user gets their own route. Also, the default routes still work. Yay.

My question is, is this insane? I am creating an entry in the route table for every user in the system. How many routes is too many? Will this kill my server if there are over 10 users? 50? 1000?

And if this is insane, how else might I accomplish this goal?

Thanks in advance. I look forward to some input from the hive-mind.

Upvotes: 4

Views: 1651

Answers (3)

Agent_9191
Agent_9191

Reputation: 7253

An alternative approach would be looking at using constraints in your MapRoute(). Keep the same values of routes.MapRoute("", "{UserName}/{action}", new { controller="user", action="Index", UserID=user.UserID});, but add the contraint that UserName needs to be in a specific format or in a list.

I don't know if it will be more performant, but it is an alternative to registering that many (nearly identical) routes. And because of the constraint it won't conflict with the default route, which you should have as the last MapRoute() call anyways, so these will be evaluated first.

Upvotes: 2

womp
womp

Reputation: 116987

There are a lot of concerns with your approach in my mind. What if someone has a username that matches one of your other controller names? You would never be able to call into that controller. Additionally, the routing system (as I understand it), tests all routes sequentially, meaning that thousands of routes would start to slow down routing lookups, including generation of Urls (like Url.Content() or Route.GetVirtualPath()).

Can't you just do

/{username}/{action}

and pass in the username as part of your parameters? What's the point of generating routes for each user if every route is going to the same controller and action methods?

If you need that to only match the User controller, consider implementing a custom route constraint. The link provides an example of creating a list of values that the controller parameter must match, but you could easily do it for your Action method names. Alternately, your custom constraint code could look up a username in the database to see if it matched.

Upvotes: 10

SirDemon
SirDemon

Reputation: 1758

I'm not sure what your limitations are, but the Routing system is built to allow you to do this with one route rather than one for each user.

A very simple example based on your own would be:

routes.MapRoute(
         "",
         "{UserName}/{action}",
         new { controller="User", action="Index", UserID=user.UserID }
     );

Upvotes: 0

Related Questions