How to make one controller the default one when only action specified?

前端 未结 1 1070
傲寒
傲寒 2021-01-25 00:05

I am using the standard MVC template from MVC 2013.

There is a Home controller with actions About, Contact, etc.

There is an Account co

相关标签:
1条回答
  • 2021-01-25 00:51

    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" }
    );
    

    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).

    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;
        }
    }
    

    Then applying the constraint:

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

    See MSDN

    0 讨论(0)
提交回复
热议问题