0

How can I map a URL in this format

http://DOMAIN/{userID}

but not overriding the default format {controller}/{action}/{id}??

I tried this but it's not working:

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

routes.MapRoute("Users", "{userID}", new { controller = "Users", action = "GetUser" });
Juan José Cumba
  • 87
  • 1
  • 2
  • 6
  • Just switch the 2 lines (move the Users routing to top) and it will work. Just keep it mind that it will capture all urls like `/home` into Users controller instead of Home controller. If you don't like that to happen they you will need a regex as constrait for the UserId – tweray Jun 02 '14 at 17:14

2 Answers2

0

You really cannot based on the information you've provided. If the UserID is in a specific format that you can match using regex, you might be able to use the route filter parameter and filter by that. That route would need to be listed above the Default route as well.

routes.MapRoute(
    name: "Users",
    url: "{userID}",
    defaults: new
    {
        controller = "Users",
        action = "GetUser",
    }, 
    new {postId = @"[\w]{3,7}" }
);

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

However, since \w is any word character, it'll still match any Controller names that are between 3 and 7 characters. If there was a more specific regex you could use, it could be accomplished.

Anthony Shaw
  • 8,146
  • 4
  • 44
  • 62
  • The regex for {UserID} is [\w]{3,7}... but If I that route above the Default route for example /Home/Index its not working :S – Juan José Cumba Jun 02 '14 at 17:15
  • because \w is any word character, it'll still match any Controller names that are between 3 and 7 characters. If there was a more specific regex you could use, it could be accomplished. – Anthony Shaw Jun 02 '14 at 17:31
  • I edited my answer to include your regex, but it still comes with the warning in the comment above. – Anthony Shaw Jun 02 '14 at 17:32
0

Insert This BEFORE the default route

routes.MapRoute("Users", "{userID}", new { controller = "Users", action = "GetUser", userID=UrlParameter.Optional });

Then the method GetUser must have a parameter named userID in order for the route handler to be able to route properly.

Update :

public class UsernameUrlConstraint : IRouteConstraint
{

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values,
                      RouteDirection routeDirection)
    {
        if (values[parameterName] != null)
        {
          // check if user exists in DB
          // if it does, return true
        }
        return false;
    }
}

In your routes :

routes.MapRoute("Users",
                "{userID}", 
                new { controller = "Users", action = "GetUser" },
                new {IsUser=new UsernameUrlConstraint()}
                );

Please note that this will hit the DB every time, so it might be a good idea to implement some memory cache (memcached, or .net memory cache) where you store the username and whether it exists or not, that way you will prevent not only db hits from users that exists but for users that don't exists. For example if someone decides to access user X 1000 times, this way you will only use the cached version instead of doing 1000 db calls.

Nikola Sivkov
  • 2,812
  • 3
  • 37
  • 63
  • In this case for example /Home is routing to /Users/GetUser... Any way to check if {userID} is a controller first and if not then go to /Users/GetUser/{userID}? – Juan José Cumba Jun 02 '14 at 17:22