ASP.NET MVC中的路由,显示URL中的用户名

Bry*_*yan 7 c# asp.net-mvc routes

我试图建立一个路线,所以我可以在URL中显示用户名,如下所示:

HTTP:// localhost1234 /约翰·

这是我的routeconfig:

 routes.MapRoute(
                name: "users", // Route name
                url: "{username}", // URL with parameters
                defaults: new { controller = "Home", action = "Index", username = "" } // Parameter defaults
            );

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

这是我的HomeController:

 public ActionResult Index(string username = "Test")
 {
   return View();
  }
Run Code Online (Sandbox Code Playgroud)

首先,URL未更改.当我username = "Test"在route-config中设置时,URL不会更改.

其次,我无法导航到我的其他控制器.如果我将URL更改为http:// localhost123/Welcome,则不会发生任何事情.它应该将我重定向到一个新页面.

我在这做错了什么?

如果我更改路由的顺序,我可以导航到其他页面,但用户名不显示在URL中.

我用谷歌搜索过,关于这个问题的所有答案都说我应该使用像上面那样的路线.

小智 9

您自己的路由将无法正常工作,因为如果网址.../Product意味着您要导航到Index()方法ProductController,它将匹配您的第一条路线(并假设"产品"是username.您需要为您的路线添加路线约束true如果username有效false则返回的定义,如果没有则返回(在这种情况下,它将尝试以下路由来查找匹配).

假设你有UserController以下方法

// match http://..../Bryan
public ActionResult Index(string username)
{
    // displays the home page for a user
}

// match http://..../Bryan/Photos
public ActionResult Photos(string username)
{
    // displays a users photos
}
Run Code Online (Sandbox Code Playgroud)

然后你需要路由定义

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.MapRoute(
            name: "User",
            url: "{username}",
            defaults: new { controller = "User", action = "Index" },
            constraints: new { username = new UserNameConstraint() }
        );
        routes.MapRoute(
            name: "UserPhotos",
            url: "{username}/Photos",
            defaults: new { controller = "User", action = "Photos" },
            constraints: new { username = new UserNameConstraint() }
        );
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Test", action = "Index", id = UrlParameter.Optional }
        );
    }

    public class UserNameConstraint : IRouteConstraint
    {
        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            List<string> users = new List<string>() { "Bryan", "Stephen" };
            // Get the username from the url
            var username = values["username"].ToString().ToLower();
            // Check for a match (assumes case insensitive)
            return users.Any(x => x.ToLower() == username);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果url是.../Bryan,它将匹配User路由,你将执行该Index()方法UserController(并且值username将是"Bryan")

如果url是.../Stephen/Photos,它将匹配UserPhotos路由,你将执行该Photos()方法UserController(并且值username将是"Stephen")

如果url是.../Product/Details/4,则路由约束将为前2个路由定义返回false,并且您将执行Details()方法ProductController

如果网址是.../Peter或者.../Peter/Photos没有用户,username = "Peter"那么它将返回404 Not Found

请注意,上面的示例代码对用户进行了硬编码,但实际上您将调用一个返回包含有效用户名的集合的服务.为避免每次请求都访问数据库,您应该考虑使用MemoryCache缓存集合.代码首先检查它是否存在,如果没有填充,则检查集合是否包含username.如果添加了新用户,您还需要确保缓存无效.