我已经在StackOverflow上阅读了一些关于此的线程,但无法使其工作。我在Global.asax的RegisterRoutes末尾有这个。
routes.MapRoute(
"Profile",
"{*url}",
new { controller = "Profile", action = "Index" }
);
基本上我想要实现的是让mydomain.com/Username指向我的成员个人资料页面。我如何设置我的控制器和RegisterRoutes才能使其正常工作?
目前mydomain.com/somethingthatisnotacontrollername出现404错误。
答案 0 :(得分:6)
您的应用程序中有一组预定义的控制器(通常少于10个),因此您可以对控制器名称设置约束,然后将其他所有控制器路由到用户配置文件:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "Home|Admin|Reports|..." }
);
routes.MapRoute(
"Profile",
"{username}/{action}",
new { controller = "Profile", action = "Details" }
);
但是,如果某些用户名与您的控制器名称相同,则无法使用。根据经验最终的经验数据,这是一个小的可能性,但它不是0%的机会。当用户名与某个控制器相同时,它自动意味着它将由第一个路由处理,因为约束不会失败。
最好的方法是将URL请求改为:
www.mydomain.com/profile/username
为什么我推荐这样做?因此,这将使其更简单,更清洁,并允许有几个不同的个人资料页面:
www.mydomain.com/profile/username
www.mydomain.com/profile/username/settings
www.mydomain.com/profile/username/messages
在这种情况下,路线定义如下:
routes.MapRoute(
"Profile",
"Profile/{username}/{action}",
new { controller = "Profile", action = "Details" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
答案 1 :(得分:2)
拥有与mydomain.com/Username
相匹配的东西并不能真正起作用,因为路由引擎无法区分
mydomain.com/someusername
和
mydomain.com/controllername
可能可能是什么,如果您的用户名方案具有一组唯一的属性,即9位数的序列,您可以定义一个路由来检查看起来像用户名的内容。
routes.MapRoute("",
"UserRoute",
"{username}",
new { controller = "Profile", action = "Index"},
new { {"username", @"\d{9}"}}
);
关键点在于,您需要为路由引擎提供一些方法来区分用户名和标准控制器操作
您可以找到有关约束here
的更多信息答案 2 :(得分:1)
我的项目有这样的要求。我所做的是创建一个如下所示的路线约束:
public class SeoRouteConstraint : IRouteConstraint
{
public static HybridDictionary CacheRegex = new HybridDictionary();
private readonly string _matchPattern = String.Empty;
private readonly string _mustNotMatchPattern;
public SeoRouteConstraint(string matchPattern, string mustNotMatchPattern)
{
if (!string.IsNullOrEmpty(matchPattern))
{
_matchPattern = matchPattern.ToLower();
if (!CacheRegex.Contains(_matchPattern))
{
CacheRegex.Add(_matchPattern, new Regex(_matchPattern));
}
}
if (!string.IsNullOrEmpty(mustNotMatchPattern))
{
_mustNotMatchPattern = mustNotMatchPattern.ToLower();
if (!CacheRegex.Contains(_mustNotMatchPattern))
{
CacheRegex.Add(_mustNotMatchPattern, new Regex(_mustNotMatchPattern));
}
}
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var matchReg = string.IsNullOrEmpty(_matchPattern) ? null : (Regex)CacheRegex[_matchPattern];
var notMatchReg = string.IsNullOrEmpty(_mustNotMatchPattern) ? null : (Regex)CacheRegex[_mustNotMatchPattern];
var paramValue = values[parameterName].ToString().ToLower();
return IsMatch(matchReg, paramValue) && !IsMatch(notMatchReg, paramValue);
}
private static bool IsMatch(Regex reg, string str)
{
return reg == null || reg.IsMatch(str);
}
}
然后在寄存器路由方法中:
routes.MapRoute("",
"UserRoute",
"{username}",
new { controller = "Profile", action = "Index"},
new { username = new SeoRouteConstraint(@"\d{9}", GetAllControllersName())}
);
方法GetAllControllersName将返回项目中由|分隔的所有控制器名称:
private static string _controllerNames;
private static string GetAllControllersName()
{
if (string.IsNullOrEmpty(_controllerNames))
{
var controllerNames = Assembly.GetAssembly(typeof(BaseController)).GetTypes().Where(x => typeof(Controller).IsAssignableFrom(x)).Select(x => x.Name.Replace("Controller", ""));
_controllerNames = string.Join("|", controllerNames);
}
return _controllerNames;
}