当仅指定动作时,如何使一个控制器成为默认控制器? [英] How to make one controller the default one when only action specified?

查看:96
本文介绍了当仅指定动作时,如何使一个控制器成为默认控制器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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,当您将OtherContollerIndex操作一起使用时,将导致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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆