【问题标题】:Routing in ASP.NET MVC, showing username in URLASP.NET MVC 中的路由,在 URL 中显示用户名
【发布时间】:2016-09-18 09:52:09
【问题描述】:

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

http://localhost1234/john

这是我的路由配置:

 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" 时,URL 没有改变。

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

我在这里做错了什么?

如果我改变路由的顺序,我可以导航到其他页面,但是用户名没有显示在 URL 中。

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

【问题讨论】:

标签: c# asp.net-mvc routes


【解决方案1】:

就其本身而言,您的路由将不起作用,因为如果 url 是 .../Product,这意味着您想导航到 ProductControllerIndex() 方法,它将匹配您的第一个路由(并假设“产品”是username。如果username 有效则返回true,如果无效则返回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路由,你将在UserController中执行Index()方法(username的值将是"Bryan"

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

如果url是.../Product/Details/4,那么路由约束对于前2个路由定义会返回false,你会执行ProductControllerDetails()方法

如果 url 是 .../Peter.../Peter/Photos 并且没有 username = "Peter" 的用户,那么它将返回 404 Not Found

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

【讨论】:

  • 如果我可以投票两次,我会的。当我意识到这一点时,我总是忘记约束并感到愚蠢。我的思绪立刻跳到我多年前不得不做的疯狂黑客行为上,当我事后回顾它时,我已经想多了。
  • 正是我所需要的,并为将来的使用提供了很好的建议,甚至是 MemoryCache 部分,干得好!
【解决方案2】:

您需要对网站不同部分的 url 进行分类,以便 url 模式匹配机制顺利进行。例如,在您的情况下,放置一个类别“个人资料”或其他任何内容。现在您的请求 url 看起来像 http://localhost1234/profile/john 和路由将是

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

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

更多信息请点击链接Routing in MVC

【讨论】:

  • 如果我不想分类?看看脸书。当您访问您的个人资料时,网址是facebook/yourusername
  • @Bryan ,实际上在上面的示例中,我将其保留给其他静态页面,例如 aboutus、constactus。您可以通过删除路由中的 Profile/ 作为 url:"{username}" 来做到这一点。在这种情况下,表单域/abc 中的任何请求 url 都将搜索相同的操作以查找 username="abc"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-11
  • 1970-01-01
  • 2014-02-15
  • 2010-11-22
  • 2010-11-13
相关资源
最近更新 更多