使用属性路由填充 Defaults RouteValueDictionary

Populate the Defaults RouteValueDictionary with attribute routing

我正在将一个 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 接受一个对象来填充 Defaults RouteValueDictionary:

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

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

有谁知道以某种方式让它工作的方法吗?

"Just make two different actions" 不是这里的选项。

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

但是,如果您只是因为 "looks cool" 而坚持更改为属性路由,那么您有几个选择。

选项 1:制定单独的操作方法

如果您使用 2 个不同的操作并从第一个开始 return 一个操作,您通常不必重写逻辑。但这是属性路由中对设置可选参数的唯一原生支持。 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 通过使用几种 internal/private 类型来加载具有属性路由的 RouteValueCollection,故意使属性路由框架不可扩展。

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

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


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

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

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