当仅指定动作时,如何使一个控制器成为默认控制器? [英] How to make one controller the default one when only action specified?
问题描述
我正在使用MVC 2013中的标准MVC模板.
I am using the standard MVC template from MVC 2013.
有一个Home
控制器,具有关于,联系人等操作.
There is a Home
controller with actions About, Contact, etc.
有一个Account
控制器,具有登录,注销等操作.
There is an Account
controller with actions Login, Logout, etc.
该应用程序部署在域website
上. URL http://website 将产生/Home/Index的输出,而不更改浏览器地址框中的url,即浏览器显示的不是Http重定向的结果.
The app is deployed at domain website
. The url http://website will produce the output of /Home/Index, without changing the url in the browser address box, ie what the browser shows is not the result of a Http redirect.
如果X不是另一个网址,我如何将url http://website/X 路由到/Home/X我的应用程序中的控制器?否则,它应该路由到/Home/X/Index.
How do I make the url http://website/X route to /Home/X if X is not another controller in my application? Otherwise it should route to /Home/X/Index.
原因是我希望 http://website/about , http://网站/联系人等没有主页.
The reason is that I would like http://website/about, http://website/contact etc without the Home.
推荐答案
幼稚的解决方案是简单地在默认值(catch-all)之上定义一条新路由,如下所示:
A naive solution would be to simply define a new route above the default (catch-all) that looks like:
routes.MapRoute(
name: "ShortUrlToHomeActions",
url: "{action}",
defaults: new { controller = "Home" }
);
此方法的问题在于它将阻止访问其他控制器的Index
(默认操作)(请求/Other
,当您将OtherContoller
与Index
操作一起使用时,将导致404,请求
The problem with this approach is that it will prevent accessing the Index
(default action) of other controllers (requesting /Other
, when you have OtherContoller
with Index
action would result in 404, requesting /Other/Index
would work).
更好的解决方案是仅在没有其他同名控制器的情况下,创建与我们的/{action}
匹配的RouteConstraint
:
A better solution would be to create a RouteConstraint
that will match our /{action}
only in case there is no other controller with the same name:
public class NoConflictingControllerExists : IRouteConstraint
{
private static readonly Dictionary<string, bool> _cache = new Dictionary<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
这篇关于当仅指定动作时,如何使一个控制器成为默认控制器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!