【问题标题】:MVC route constraint custom attributeMVC 路由约束自定义属性
【发布时间】:2016-01-22 16:51:49
【问题描述】:

我想设置一个自定义路由约束,允许我用属性装饰控制器,这样我就不必将字符串传递给路由并记住用新的控制器名称更新它。

我以为我可以设置使用IRouteConstraint,但我似乎无法获得该属性。也许我只是在这里遗漏了一些明显的东西。

routes.MapRoute("test", 
    "foo/{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new { controller = new TestConstraint()}
);

routes.MapRoute("Default", "{controller}/{action}/{id}", 
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);



public class TestConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, 
        RouteValueDictionary values,
        RouteDirection routeDirection)
    {
        return false;
    }
}

[AttributeUsage(AttributeTargets.Class)]
public class CustomConstraintControllerAttribute : Attribute
{

}

[CustomConstraintController]
public class TestController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

编辑:

当前方法:

routes.MapSubdomainRoute("Store",
    "{store}/{controller}/{action}/{id}",
    new {controller = "Home", action = "Index", id = UrlParameter.Optional},
    new {controller = "StoreHome|Contacts|..." }
    );

此路由配置确保 url 必须匹配 subdomain.test.com/GiggleInc/Contactssubdomain.test.com/GiggleInc/StoreHome

subdomain.test.com/GiggleInc/StoreHome
MapSubdomainRoute /{store}  /{controller}/{action}/{id}

此方法要求以这种方式使用的每个控制器必须添加到控制器约束中。

正如我在 cmets 中提到的,我想替换属性或类似内容的硬编码字符串。

【问题讨论】:

  • 路由已完全完成控制器被选中。您希望通过约束实现什么?
  • 请注意,您可以使用 Attribute Routes 在 MVC 5 中完全设置路由(包括约束),只需将您的路由配置与您的控制器一起放置。
  • 这就是我所害怕的。根据我的研究,这就是我认为的答案。我们在项目中使用子域,某些控制器需要存在子域。目前,我们用控制器类名作为字符串填充约束。我希望改为装饰班级
  • 虽然如果我在return false 上放置一个断点,它会在请求开始时被命中。我想我可以在AuthorizeAttribute中使用ControllerDescriptor之类的东西
  • 请更新您的问题,详细说明您要达到的目标。目前还不清楚AuthorizeAttribute 尚未涵盖的情况。如果用户尝试访问他们“不允许”访问的控制器,您究竟希望应用程序做什么?

标签: asp.net-mvc


【解决方案1】:

首先,感谢您提供这行我不知道的甜蜜代码:

constraints: new { controller = "StoreHome|Contacts" }

我不知道我可以如此轻松地将我的 MapRoute 过滤到控制器列表中。
其次,您不需要为此实现自定义 IRouteConstraint。
MVC 提供了您正在寻找的属性路由。

您甚至可以包括默认/可选值,就像在 MapRoute 中一样。
像这样装饰你的控制器类:

[RoutePrefix("{store}/Test")]
[Route("{action=Index}/{id?}")]//Without this, you need to define "[Route]" above every Action-Method.
public class TestController : Controller
{
    public ActionResult Index(string store)//Adding "string store" is optional.
    {
        return View();
    }
}

就是这样。
请记住在每个控制器下的所有操作中添加“store”参数(但这不是必需的)。

注意
如果您使用 Attributes 而不是 MapRoute,那么您将能够在没有“store”前缀的情况下访问控制器。
使用自定义和默认 MapRoutes,您可以通过任何一种方式访问​​您的控制器。
通过使用这些属性装饰您的控制器,您现在强制它只使用这个确切的路径。
这可能是您想要的,但如果您从 Visual Studio 在您的一个视图上启动 IIS Express,它将找不到它,因为 Visual Studio 不知道为您添加 RoutePrefix。

有关属性路由的更多信息,请参阅此链接:
https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/

【讨论】:

  • 你在哪里使用constraints: new { controller = "StoreHome|Contacts" }
  • @Seabizkit 我在routes.MapRoute() 函数中使用了它。请参阅我的其他答案以获得更好的示例:stackoverflow.com/a/52033013/555798
  • 谢谢,当您使用更高级的上下文相关路由并且已经拥有区域时,很难找到有关如何/应该如何构建项目/项目的信息,我已经让它工作了,但会很好查找有关如何构建的信息示例。试图问让我无处可去softwareengineering.stackexchange.com/questions/398700/…
【解决方案2】:

试试这个...

public class TestRouteAttribute : RouteFactoryAttribute
{      
    public TestRouteAttribute(string template) : base(template) { }

    public override RouteValueDictionary Constraints
    {
        get
        {
            var constraints = new RouteValueDictionary();
            constraints.Add("TestConstraint", new TestConstraint());
            return constraints;
        }
    }
}

那么你应该可以使用[TestRoute]来装饰你的动作方法

顺便说一句,如果有人知道的话,我很想知道如何在 asp.net core 中完成这项工作。

【讨论】:

  • 我应该使用[TestRoute("{template}")] 代替[Route("{template}")] 还是除此之外?
猜你喜欢
  • 1970-01-01
  • 2015-02-06
  • 1970-01-01
  • 1970-01-01
  • 2019-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多