一尘不染

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

c#

我正在尝试进行路由,以便可以在URL中显示用户名,如下所示:

http:// localhost1234 / john

这是我的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 }
            );

这是我的HomeController:

 public ActionResult Index(string username = "Test")
 {
   return View();
  }

首先,URL不变。当我username = "Test"在route-config中进行设置时,URL不会更改。

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

我在这里做错了什么?

如果更改路线顺序,则可以导航到其他页面,但用户名未显示在URL中。

我已经用谷歌搜索,关于这个问题的所有答案都说我应该使用上述路线。


阅读 244

收藏
2020-05-19

共1个答案

一尘不染

就其本身而言,您的路由将不起作用,因为如果url
.../Product意味着您想要导航至的Index()方法ProductController,则它将与您的第一个路由匹配(并假设“
Product”为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
}

然后您需要定义路线

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

如果url为.../Bryan,则它将与User路由匹配,并且您将在中执行Index()方法UserController(并且的值username将为"Bryan"

如果url为.../Stephen/Photos,则它将与UserPhotos路由匹配,并且您将在中执行Photos()方法UserController(并且的值username将为"Stephen"

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

如果url为.../Peteror .../Peter/Photos且没有用户使用,username = "Peter"则它将返回404 Not Found

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

2020-05-19