用户登录前,路由为:
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 }
);
}
}
我应该怎么做才能将路由更改为用户名?
您需要添加一条路由来覆盖具有用户名的案例。
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重定向即可。您可以在全局过滤器中进行此操作。
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会在生成URL时自动重用请求中的路由值,因此无需更改任何ActionLinks
包含的内容username
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句