MVC备用路由失败,带有可选参数

时间:2014-10-08 01:11:27

标签: c# model-view-controller routing

我正在尝试在 MVC 5 网络应用中实施替代路由。

我有控制器代码:

namespace MyMvcProject.Web.Controllers
{
    [RoutePrefix("account")]
    public class AccountController : Controller {


        [Route("{param}")]
        [Authorize]
        public ActionResult Index(string param = null) {

...

在点击网址时效果很好:http://example.com/account/testparam。 但是,我希望能够将值param作为可选参数。

我尝试将[Route("{param}")]更改为[Route("{param}*")],但从未输入Index()方法。我也尝试将其更改为[Route("{param:string=Test}")],但我遇到了一个使用术语string的路由运行时错误。

我的RoutConfig.cs包含:

 public static void RegisterRoutes(RouteCollection routes) 
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapMvcAttributeRoutes();

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{param}",
                defaults: new { controller = "Home", action = "Index", param = UrlParameter.Optional }
            );
        }

有没有人知道如何使用这种替代路由语法强制Index()拥有可选参数?它在我的应用的其他部分非常有用,所以我想保留RoutePrefixRoute装饰器。

更新

我还在尝试解决这个问题,所以我将路线装饰器更改为[Route("{param:int=0}")],将构造函数更改为public ActionResult Index(int id),它按预期工作(即http://example.com/account行为就像输入http://example.com/account/0一样。这正是我想要的,只使用string数据类型。

当我将装饰器更改为:[Route("{id:string=\"\"}")]并将构造函数更改为public ActionResult Index(string id)时,我看到了运行时错误:

  

类型' DefaultInlineConstraintResolver'的内联约束解析器无法解决以下内联约束:' string'。

2 个答案:

答案 0 :(得分:6)

找到答案here。我需要使用param使?成为可空的。

[Route("{param?}")]
[Authorize]
public ActionResult Index(string param = null) {
   ...
}

希望这将有助于将来的某些人。 我在这个主题上找不到很多参考文献。

答案 1 :(得分:6)

@ Brett 答案很棒:将?添加到Route属性中的参数,然后在Action签名中提供默认值允许该参数是可选的。

这是Mike Wasson在Attribute Routing in Web API 2上发表的精彩文章,其中包括一篇关于可选参数的文章。

迈克还谈到应用多个约束,并说:

  

您可以对参数应用多个约束,用冒号分隔。

  [Route("users/{id:int:min(1)}")]
  public User GetUserById(int id) { ... }

这也很有效...直到你想要多个约束一个可选参数。

我们知道,应用?允许参数是可选的。因此,采用上面的例子,人们可能会认为

[Route("users/{id:int?:min(1)}")]
public User GetUserById(int id = 1) { ... }

id参数约束为大于0的整数,或为空(在这种情况下,使用默认值1)。实际上,我们收到错误消息:

  

类型' DefaultInlineConstraintResolver'的内联约束解析器无法解决以下内联约束:' int?'。

事实证明,约束的顺序很重要!只需在所有其他约束之后放置可选约束? 就可以得到预期的行为

[Route("users/{id:min(1):int?}")]
public User GetUserById(int id = 1) { ... }

这也适用于2个以上的约束,例如

[Route("users/{id:min(1):max(10):int?}")]
public User GetUserById(int id = 1) { ... }