我正在使用 MVC 2013 中的标准 MVC 模板。
有一个
Home
控制器,具有“关于”、“联系”等操作。
有一个
Account
控制器,具有登录、注销等操作。
该应用程序部署在域
website
。 url http://website 将产生 /Home/Index 的输出,而不改变浏览器地址框中的 url,即浏览器显示的不是 Http 重定向的结果。
如果 X 不是我的应用程序中的另一个控制器,如何将 url http://website/X 路由到 /Home/X?否则它应该路由到/Home/X/Index。
原因是我想要 http://website/about、http://website/contact 等而不需要主页。
一个简单的解决方案是简单地在默认(包罗万象)之上定义一条新路由,如下所示:
routes.MapRoute(
name: "ShortUrlToHomeActions",
url: "{action}",
defaults: new { controller = "Home" }
);
这种方法的问题在于,它将阻止访问其他控制器的
Index
(默认操作)(请求 /Other
,当你有 OtherContoller
和 Index
操作时会导致 404,请求 /Other/Index
会导致 404 错误)工作)。
更好的解决方案是创建一个
RouteConstraint
,仅在没有其他同名控制器的情况下才与我们的 /{action}
匹配:
public class NoConflictingControllerExists : IRouteConstraint
{
private static readonly ConcurrentDictionary<string, bool> _cache = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var path = httpContext.Request.Path;
if (path == "/" || String.IsNullOrEmpty(path))
return false;
if (_cache.ContainsKey(path))
return _cache[path];
IController ctrl;
try
{
var ctrlFactory = ControllerBuilder.Current.GetControllerFactory();
ctrl = ctrlFactory.CreateController(httpContext.Request.RequestContext, values["action"] as string);
}
catch
{
_cache.Add(path, true);
return true;
}
var res = ctrl == null;
_cache.Add(path, res);
return res;
}
}
然后应用约束:
routes.MapRoute(
name: "ShortUrlToHomeActions",
url: "{action}",
defaults: new { controller = "Home" },
constraints: new { noConflictingControllerExists = new NoConflictingControllerExists() }
);
参见MSDN