views:

817

answers:

7

I must be dense. After asking several questions on StackOverflow, I am still at a loss when it comes to grasping the new routing engine provided with ASP.NET MVC. I think I've narrowed down the problem to a very simple one, which, if solved, would probably allow me to solve the rest of my routing issues. So here it is:

How would you register a route to support a Twitter-like URL for user profiles?

www.twitter.com/username

Assume the need to also support:

  • the default {controller}/{action}/{id} route.

  • URLs like:

    www.twitter.com/login
    www.twitter.com/register

Is this possible?

+1  A: 

Check this question: How does Web Routing Work?

John
A: 

You could handle that in the home controller, but the controller method would not be very elegant. I'm guessing something like this might work (not tested):

routes.MapRoute(
    "Root",
    "{controller}/{view}",
    new { controller = "Home", action = "Index", view = "" }
);

Then in your HomeController:

public ActionResult Index(string view) {
    switch (view) {
        case "":
            return View();

        case "register":
            return View("Register");

        default: 
            // load user profile view
    }
}
John Sheehan
Even if this works, I'm not suggesting you do it. It smells :)
John Sheehan
+7  A: 

What about

routes.MapRoute(
    "Profiles",
    "{userName}",
    new { controller = "Profiles", action = "ShowUser" }
);

and then, in ProfilesController, there would be a function

public ActionResult ShowUser(string userName)
{
...

In the function, if no user with the specified userName is found, you should redirect to the default {controller}/{action}/{id} (here, it would be just {controller}) route.

Urls like www.twitter.com/login should be registered before that one.

routes.MapRoute(
    "Login",
    "Login",
    new { controller = "Security", action = "Login" }
);
gius
+3  A: 

The important thing to understand is that the routes are matched in the order they are registered. So you would need to register the most specific route first, and the most general last, or all requests matching the general route would never reach the more specific route.

For your problem i would register routing rules for each of the special pages, like "register" and "login" before the username rule.

AndreasN
A: 

OK I haven't ever properly tried this, but have you tried to extend the RouteBase class for dealing with users. The docs for RouteBase suggest that the method GetRouteData should return null if it doesn't match the current request. You could use this to check that the request matches one of the usernames you have.

You can add a RouteBase subclass using:

  routes.Add(new UserRouteBase());

When you register the routes.

Might be worth investigating.

Jennifer
+1  A: 

i think your question is similar to mine. http://stackoverflow.com/questions/1442803/asp-net-mvc-routing

this is what robert harvey answered.

routes.MapRoute( _
    "SearchRoute", _
    "{id}", _
    New With {.controller = "User", .action = "Profile", .id = ""} _

)

mcxiand
A: 

Here is an alternative way to standar route registration:

1. Download RiaLibrary.Web.dll and reference it in your ASP.NET MVC website project

2. Decoreate controller methods with the [Url] Attributes:

public SiteController : Controller
{
    [Url("")]
    public ActionResult Home()
    {
        return View();
    }

    [Url("about")]
    public ActionResult AboutUs()
    {
        return View();
    }

    [Url("store/{?category}")]
    public ActionResult Products(string category = null)
    {
        return View();
    }
}

BTW, '?' sign in '{?category}' parameter means that it's optional. You won't need to specify this explicitly in route defaults, which is equals to this:

routes.MapRoute("Store", "store/{category}",
new { controller = "Store", action = "Home", category = UrlParameter.Optional });

3. Update Global.asax.cs file

public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoutes(); // This do the trick
    }

    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
    }
}

How to set defaults and constraints? Example:

public SiteController : Controller
{
    [Url("admin/articles/edit/{id}", Constraints = @"id=\d+")]
    public ActionResult ArticlesEdit(int id)
    {
        return View();
    }

    [Url("articles/{category}/{date}_{title}", Constraints =
         "date=(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])")]
    public ActionResult Article(string category, DateTime date, string title)
    {
        return View();
    }
}

How to set ordering? Example:

[Url("forums/{?category}", Order = 2)]
public ActionResult Threads(string category)
{
    return View();
}

[Url("forums/new", Order = 1)]
public ActionResult NewThread()
{
    return View();
}
Koistya Navin