【问题标题】:ASP .NET MVC 5.2 Inherited Route: Multiple controller types were found that match the URLASP .NET MVC 5.2 Inherited Route:找到与 URL 匹配的多个控制器类型
【发布时间】:2018-07-22 05:52:09
【问题描述】:

我正在尝试使用具有[InheritedRoute] 属性的基本控制器。基类和控制器是这样创建的:

[InheritedRoute("app/{controller}/{action=index}/{id?}")]
public abstract class MyBaseController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

public class DefaultController : MyBaseController { }

public class KyleController : MyBaseController { }

[RoutePrefix("app/support")]
[Route("{action=Index}/{id?}")]
public class SupportController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

InheritedRouteAttribute 类和东西:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class InheritedRouteAttribute : Attribute, IDirectRouteFactory
{
    public string Name { get; set; }
    public int Order { get; set; }
    public string Template { get; }

    public InheritedRouteAttribute(string template)
    {
        this.Template = template;
    }

    public RouteEntry CreateRoute(DirectRouteFactoryContext context)
    {
        var controllerDescriptor = context.Actions.First().ControllerDescriptor;
        var controllerName = controllerDescriptor.ControllerName;
        string template;
        if (string.Equals(controllerName, "Default", StringComparison.OrdinalIgnoreCase))
        {
            template = this.Template.Replace("{controller}/", string.Empty);
        }
        else
        {
            template = this.Template.Replace("{controller}", controllerName);
        }

        IDirectRouteBuilder builder = context.CreateBuilder(template);
        builder.Name = this.Name ?? controllerName + "_Route";
        builder.Order = this.Order;

        return builder.Build();
    }
}

public class InheritedDirectRouteProvider : DefaultDirectRouteProvider
{
    protected override IReadOnlyList<IDirectRouteFactory> GetControllerRouteFactories(ControllerDescriptor controllerDescriptor)
    {
        return controllerDescriptor.GetCustomAttributes(typeof(IDirectRouteFactory), true).Cast<IDirectRouteFactory>().ToArray();
    }
}

在我的 RouteConfig.cs 中,我没有使用常规路由:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapMvcAttributeRoutes(new InheritedDirectRouteProvider());
}

本质上,我想这样做,如果用户在DefaultController 中,则从 URL 中删除“默认”一词;否则,使用以“app”开头的标准约定。如果我去掉默认值(通过去掉 {controller}/),那么每当我转到另一个 URL 时,我都会收到多个控制器类型错误。但是,如果我离开它,一切都很好,只是 URL 不是我想要的。

我正在查看 RouteDebugger 并查看注册为我的路线的内容,我看到了(如我所料):

  • app/Kyle/{action}/{id}
  • app/support/{action}/{id}
  • app/{action}/{id}

我错过了什么?为什么它认为我有重复的路线,特别是在SupportControllerDefaultController

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-5 routes asp.net-mvc-5.2 attributerouting


    【解决方案1】:

    我们来看看这两个路由模板:

    • app/support/{action=Index}/{id?}
    • app/{action=index}/{id?}

    如果你访问app/support,它们都会匹配:

    • app/support/{action=Index}/{id?} - 默认情况下操作为“索引”,缺少 id(可选)。
    • app/{action=index}/{id?} - 操作为“支持”(!),缺少 id(可选)。

    如果您访问app/support/something,两条路线也匹配:

    • app/support/{action=Index}/{id?} - 操作是“某事”,缺少 id(可选)。
    • app/{action=index}/{id?} - 操作是“支持”,id 是“某事”。

    因此,“app/support”下的任何具有 2 或 3 个段的 url 都将匹配两个路由。

    现在,当您了解发生了什么时,您可能可以自己解决问题。最简单的解决方法可能是使这些路由匹配不同数量的段。可能的选项是删除两个路由的默认操作并摆脱可选的 id 参数:

    • 应用/支持/{action}
    • 应用/{动作}

    选择满足您要求的解决方案。但请确保一条路线中的“支持”部分与您当前路线中的另一条路线中的操作部分不匹配。

    【讨论】:

    • 天哪。盯着它看了好几天,让一个好人解释它,就像“笨蛋。我知道。我怎么会错过它?”谢谢! (我只是一直说“不,我在第二条路线上看不到控制器!”)
    猜你喜欢
    • 1970-01-01
    • 2016-07-27
    • 2020-02-05
    • 2017-03-13
    • 1970-01-01
    • 2023-04-06
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多