MVC 4,MapRoute for / {parameter} URL

时间:2014-06-02 17:08:43

标签: asp.net-mvc asp.net-mvc-4 maproute

如何以此格式映射网址

http://DOMAIN/{userID}

但不覆盖默认格式{controller} / {action} / {id} ??

我尝试了这个,但它不起作用:

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" });

2 个答案:

答案 0 :(得分:0)

您实际上无法根据您提供的信息。如果UserID采用可以使用正则表达式匹配的特定格式,则可以使用路由过滤器参数并按此过滤。该路线也需要列在默认路线上方。

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 }
);

但是,由于\ w是任何单词字符,它仍将匹配3到7个字符之间的任何控制器名称。如果您可以使用更具体的正则表达式,则可以完成。

答案 1 :(得分:0)

在默认路线之前插入此

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

然后方法GetUser必须有一个名为userID的参数,以便路由处理程序能够正确路由。

更新:

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;
    }
}

在您的路线中:

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

请注意,每次都会打开数据库,所以实现一些内存缓存(memcached或.net内存缓存)可能是个好主意,你可以在其中存储用户名以及是否存在,就像你一样将不仅防止存在的用户的db命中,而且防止不存在的用户的db命中。例如,如果有人决定访问用户X 1000次,这样您将只使用缓存版本而不是1000 db调用。