使用属性路由填充默认值RouteValueDictionary

时间:2016-05-06 08:43:04

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

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

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

我的简化控制器操作:

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

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

有没有人知道如何以这种或那种方式工作?

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

1 个答案:

答案 0 :(得分:1)

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

但是如果你坚持改变属性路由只是因为它看起来很酷"那么你有几个选择。

选项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。这需要使用Reflection,但由于它在应用程序启动时运行而不是按请求运行,因此整体性能影响最小。

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

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

  1. Attributes have limitations on which datatypes are supported,而不是基于代码的解决方案。
  2. 使用属性路由时,包括填充默认路由值,使用约束和构建自定义路由等功能要困难得多或不受支持。
  3. 底线是,属性路由不是路由的圣杯。它是MVC 5中添加的另一个路由选项,可以在基于约定的路由能够的有限路由场景子集下使用。它不是也不应该被视为路由"升级"只是因为它恰好在MVC 5之前不是一个选项。