如果仅指定了操作,如何使一个控制器成为默认控制器?

时间:2015-04-01 08:30:40

标签: asp.net-mvc asp.net-mvc-routing

我正在使用MVC 2013中的标准MVC模板。

有一个Home控制器,其中有关于,联系等的操作

有一个Account控制器,其中包含登录,注销等操作

该应用已部署在域website。网址http://website将生成/ Home / Index的输出,而不更改浏览器地址框中的网址,即浏览器显示的内容不是Http重定向的结果。

如果X不是我的应用程序中的另一个控制器,如何将URL http://website/X路由到/ Home / X?否则它应该路由到/ Home / X / Index。

原因是我想要http://website/abouthttp://website/contact等没有主页。

1 个答案:

答案 0 :(得分:2)

一个天真的解决方案是简单地定义一个高于默认值(全能)的新路线,如下所示:

routes.MapRoute(
    name: "ShortUrlToHomeActions",
    url: "{action}",
    defaults: new { controller = "Home" }
);

此方法存在的问题是,当您Index行动/Other时,它会阻止访问其他控制器的OtherContoller(默认操作)(请求Index}将导致404,请求/Other/Index将起作用。

更好的解决方案是创建一个RouteConstraint,只有在没有其他控制器具有相同名称的情况下才会匹配/{action}

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