登录后如何更改路由到用户名?
Posted
技术标签:
【中文标题】登录后如何更改路由到用户名?【英文标题】:How to change route to username after logged in? 【发布时间】:2016-08-28 00:28:35 【问题描述】:用户登录前,路由为:
localhost:54274/Home
localhost:54274/Home/About
localhost:54274/Home/Contact
localhost:54274/Home/Login
localhost:54274/Home/Register
用户登录后,路由为:
1. localhost:54274/Project
2. localhost:54274/Project/Create
3. localhost:54274/Project/Edit/1
4. localhost:54274/Project/Delete/2
5. localhost:54274/Project/1/Requirement
6. localhost:54274/Project/1/Requirement/Create
7. localhost:54274/Project/1/Requirement/Edit/3
8. localhost:54274/Project/1/Requirement/Delete/4
我希望在用户登录后将路由更改为用户名。例如,用户名是hendyharf。
1. localhost:54274/hendyharf/Project
2. localhost:54274/hendyharf/Project/Create
3. localhost:54274/hendyharf/Project/Edit/1
4. localhost:54274/hendyharf/Project/Delete/2
5. localhost:54274/hendyharf/Project/1/Requirement
6. localhost:54274/hendyharf/Project/1/Requirement/Create
7. localhost:54274/hendyharf/Project/1/Requirement/Edit/3
8. localhost:54274/hendyharf/Project/1/Requirement/Delete/4
我项目的控制器只有 3 个控制器:HomeController
、ProjectController
和 RequirementController
我的RouteConfig.cs
仍处于默认状态
public static void RegisterRoutes(RouteCollection routes)
routes.IgnoreRoute("resource.axd/*pathInfo");
routes.MapRoute(
name: "Default",
url: "controller/action/id",
defaults: new controller = "Home", action = "Index", id = UrlParameter.Optional
);
我应该怎么做才能将路由更改为用户名?
【问题讨论】:
您可以使用属性路由而不是传统路由exceptionnotfound.net/attribute-routing-vs-convention-routing @AbbasGaliyakot 你能给我一些关于我的问题的小例子吗? 对于从 5 开始编号的路线,为什么会有 /Project/1/ ?因为它的需求控制器,它应该没有 /Project/1/ 。有任何理由为路由和数字“1”设置 2 个控制器名称? @KarthikMR 哦,是的,我想像 Windows 中的目录一样创建路由,例如 C:/Program Files/Microsoft/... 所以我的意思是,在 1 号路由上,它将是项目的查看页面列表,一旦您单击项目,它将引导您到名为 Requirement 的页面,并且还会有一个需求列表,您可以做一些 CRUD 的事情 【参考方案1】:你需要添加一个路由来覆盖有用户名的情况。
public static void RegisterRoutes(RouteCollection routes)
routes.IgnoreRoute("resource.axd/*pathInfo");
routes.MapRoute(
name: "Username_Default",
url: "username/controller/action/id",
defaults: new controller = "Home", action = "Index", id = UrlParameter.Optional ,
constraints: new username = new OwinUsernameConstraint()
);
routes.MapRoute(
name: "Default",
url: "controller/action/id",
defaults: new controller = "Home", action = "Index", id = UrlParameter.Optional
);
但要使其正常工作,您需要在 URL 中添加一个文字字符串以将段标识为用户名(即username-username\
),或者您需要制定一个仅允许以下用户名的约束在数据库中。这是后者的一个例子:
using MvcUsernameInUrl.Models;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Web.Routing;
namespace MvcUsernameInUrl
public class OwinUsernameConstraint : IRouteConstraint
private object synclock = new object();
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
if (parameterName == null)
throw new ArgumentNullException("parameterName");
if (values == null)
throw new ArgumentNullException("values");
object value;
if (values.TryGetValue(parameterName, out value) && value != null)
string valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
return this.GetUsernameList(httpContext).Contains(valueString);
return false;
private IEnumerable<string> GetUsernameList(HttpContextBase httpContext)
string key = "UsernameConstraint.GetUsernameList";
var usernames = httpContext.Cache[key];
if (usernames == null)
lock (synclock)
usernames = httpContext.Cache[key];
if (usernames == null)
// Retrieve the list of usernames from the database
using (var db = ApplicationDbContext.Create())
usernames = (from users in db.Users
select users.UserName).ToList();
httpContext.Cache.Insert(
key: key,
value: usernames,
dependencies: null,
absoluteExpiration: Cache.NoAbsoluteExpiration,
slidingExpiration: TimeSpan.FromSeconds(15),
priority: CacheItemPriority.NotRemovable,
onRemoveCallback: null);
return (IEnumerable<string>)usernames;
注意:我强烈建议在示例中为此使用缓存,因为路由约束在每个请求上运行,并且在每个请求上都访问数据库并不好.这样做的缺点是用户名在注册后最多需要 15 秒才能激活。除了将记录添加到数据库之外,您还可以通过在注册新帐户时更新缓存(以线程安全的方式)来解决此问题,这将使其在路由约束中立即可用。
然后,只需在用户登录时执行 302 重定向即可。您可以在 global filter 中执行此操作。
using System.Web;
using System.Web.Mvc;
namespace MvcUsernameInUrl
public class RedirectLoggedOnUserFilter : IActionFilter
public void OnActionExecuting(ActionExecutingContext filterContext)
var routeValues = filterContext.RequestContext.RouteData.Values;
bool isLoggedIn = filterContext.HttpContext.User.Identity.IsAuthenticated;
bool requestHasUserName = routeValues.ContainsKey("username");
if (isLoggedIn && !requestHasUserName)
var userName = filterContext.HttpContext.User.Identity.Name;
// Add the user name as a route value
routeValues.Add("username", userName);
filterContext.Result = new RedirectToRouteResult(routeValues);
else if (!isLoggedIn && requestHasUserName)
// Remove the user name as a route value
routeValues.Remove("username");
filterContext.Result = new RedirectToRouteResult(routeValues);
public void OnActionExecuted(ActionExecutedContext filterContext)
// Do nothing
用法
public class FilterConfig
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
filters.Add(new RedirectLoggedOnUserFilter());
filters.Add(new HandleErrorAttribute());
MVC 将automatically reuse route values from the request when genrating URLs,因此无需更改您的任何ActionLinks
以包含username
。
Here is a working demo 在 GitHub 上使用 MVC5、OWIN 和 ASP.NET Identity。
【讨论】:
我很抱歉我的新问题,我忘了在这个问题中改进我的细节,所以我决定创建一个新问题。但无论如何,非常感谢您提供非常详细的答案!这真的很有帮助!对不起,我是 *** 的新手,所以我现在才打开 ***以上是关于登录后如何更改路由到用户名?的主要内容,如果未能解决你的问题,请参考以下文章