我正在将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属性无法处理匿名类型的编译时间。
有没有人知道如何以这种或那种方式工作?
“只做两个不同的行动”在这里不是一个选择。
答案 0 :(得分:1)
首先,不清楚为什么要将基于约定的路由更改为(不太灵活)基于属性的路由,特别是考虑到后者不支持您感兴趣的某些功能。 / p>
但是如果你坚持改变属性路由只是因为它看起来很酷"那么你有几个选择。
如果你使用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);
}
Microsoft故意通过使用多个内部/私有类型来加载具有属性路由的RouteValueCollection
,从而使属性路由框架不可扩展。
您可能会破坏属性路由框架以提供自己的逻辑as I have done here。这需要使用Reflection,但由于它在应用程序启动时运行而不是按请求运行,因此整体性能影响最小。
但是根据您的要求,您可能需要从MVC属性路由框架中复制更多逻辑来填充您的路由,这可能不值得付出努力。在我支持多种文化的简单案例中。在您的情况下,您需要使用其他参数支持您自己的属性类型,这将更具挑战性。
但是如果你需要比这更多的灵活性,我建议坚持使用基于约定的路由。
底线是,属性路由不是路由的圣杯。它是MVC 5中添加的另一个路由选项,可以在基于约定的路由能够的有限路由场景子集下使用。它不是也不应该被视为路由"升级"只是因为它恰好在MVC 5之前不是一个选项。