只指定动作时如何将某个控制器设置为默认控制器?

问题描述 投票:0回答:1

我正在使用 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/abouthttp://website/contact 等而不需要主页。

asp.net-mvc asp.net-mvc-routing
1个回答
2
投票

一个简单的解决方案是简单地在默认(包罗万象)之上定义一条新路由,如下所示:

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

© www.soinside.com 2019 - 2024. All rights reserved.