【问题标题】:Populate the Defaults RouteValueDictionary with attribute routing使用属性路由填充 Defaults RouteValueDictionary
【发布时间】:2016-05-06 08:43:03
【问题描述】:

我正在将 ASP.NET MVC 4 项目升级到 MVC 5,并希望使用属性路由而不是约定路由。到目前为止,一切都很好,但是我在填充 Defaults RouteValueDictionary 时遇到了一个问题。这如何通过属性路由来实现?

我对同一个动作使用多个路由,每个路由都传递一个不同的枚举值来确定动作是哪种类型。枚举的值不会直接在路由中可见!这很重要,否则我可以在路由模板中使用枚举参数的值。

我的简化控制器动作:

public class MyController : Controller
{
    public ActionResult MyAction(MyType myTypeValue)
    {
        // ...
    }
}

public enum MyType
{
    FirstOption,
    SecondOption
}

我的旧会议路线:

routes.Add("First", new Route("a-route", new { controller = "MyController", action = "MyAction", myTypeValue = MyType.FirstOption }));
routes.Add("Second", new Route("a-total/different-route", new { controller = "MyController", action = "MyAction", myTypeValue = MyType.Second }));

通过属性路由,我期望使用这样的东西:

Route["a-route", new { myTypeValue = MyType.FirstOption }]
Route["a-total/different-route", new { myTypeValue = MyType.SecondOption }]

但不幸的是,这并不存在。我试图制作一个自定义的RouteAttribute,它接受一个对象来填充DefaultsRouteValueDictionary

public class MyRouteAttribute : RouteFactoryAttribute
{
    private RouteValueDictionary _defaults;

    public Route(string template, object defaults)
    :base(template)
    {
        _defaults = new RouteValueDictionary(defaults);
    }

    public override RouteValueDictionary Defaults
    {
        get { return _defaults; }
    }
}

但这不起作用,因为路由属性无法处理匿名类型的编译时间。

有没有人知道如何让这个工作以一种或另一种方式工作?

“只做两个不同的动作”在这里不是一个选项。

【问题讨论】:

    标签: c# asp.net-mvc enums asp.net-mvc-routing attributerouting


    【解决方案1】:

    首先,不清楚为什么要从基于约定的路由更改为(不太灵活的)基于属性的路由,特别是考虑到后者不支持您感兴趣的某些功能。

    但是,如果您坚持更改为属性路由只是因为它“看起来很酷”,那么您有几个选择。

    选项 1:创建单独的操作方法

    如果您使用 2 个不同的操作并从第一个操作返回一个操作,您通常不必重写逻辑。但这是设置可选参数的属性路由中唯一的原生支持。如何使用Enum 支持可选参数的示例可以是found here

    [Route("a-route")]
    public ActionResult MyAction(MyType myTypeValue = MyType.FirstOption)
    {
        return View("Index");
    }
    
    [Route("a-total/different-route")]
    public ActionResult My2ndAction(MyType myTypeValue = MyType.SecondOption)
    {
        return MyAction(myTypeValue);
    }
    

    选项 2:破解属性路由框架

    Microsoft 通过使用几种内部/私有类型来加载带有属性路由的RouteValueCollection,故意使属性路由框架不可扩展。

    您可能会破解属性路由框架以提供您自己的逻辑as I have done here。这需要使用反射,但由于它在应用程序开始时运行而不是按请求运行,因此整体性能影响将是最小的。

    但是根据您的要求,您可能需要从 MVC 属性路由框架中复制更多逻辑来填充您的路由,这可能不值得付出努力。在我支持多种文化的简单案例中。在您的情况下,您将需要使用其他参数来支持您自己的属性类型,这将更具挑战性。


    但如果您需要比这更大的灵活性,我建议您坚持使用基于约定的路由。

    1. Attributes have limitations on which datatypes are supported 而不是基于代码的解决方案。
    2. 使用属性路由时,包括填充默认路由值、使用约束和构建自定义路由在内的一些功能要么更加困难,要么不受支持。

    归根结底,属性路由不是路由的圣杯。它是 MVC 5 中添加的另一个路由选项,可以在基于约定的路由能够实现的有限路由场景子集下使用。它不是也不应该被视为路由“升级”,因为它恰好在 MVC 5 之前不是一个选项。

    【讨论】:

    • 感谢您的明确答复。我不会仅仅因为它“看起来很酷”而切换到属性路由,而是主要是为了可维护性。对于超过 200 条不同的路线,很难确定哪些路线属于哪些动作,因此属性非常方便。我想我将采用混合解决方案,其中默认枚举值路由将按属性完成,而其他枚举值路由基于约定。
    • 听起来是一个合理的解决方案。祝你好运!
    猜你喜欢
    • 1970-01-01
    • 2020-03-06
    • 1970-01-01
    • 1970-01-01
    • 2019-02-11
    • 2013-05-29
    • 1970-01-01
    • 2016-09-09
    • 2021-10-22
    相关资源
    最近更新 更多