ASP.NET MVC路由休息标准URL参数

时间:2011-06-21 12:06:48

标签: .net asp.net-mvc vb.net asp.net-mvc-routing maproute

有点噩梦,希望我只是愚蠢。

我有以下控制器操作:

<HttpGet()>
Function News() As ActionResult
End Function

<HttpGet()>
Function News(ByVal id As Integer) As ActionResult
End Function

我希望它是聪明的,如果我在网址中没有ID,则转到第一个,如果有,则转到第二个。

我收到以下错误:

  

当前关于控制器类型'MarketsController'的操作'新闻'请求在以下操作方法之间是不明确的:   TradeChaseMVC.MarketsController类型的System.Web.Mvc.ActionResult News()   TradeChaseMVC.MarketsController类型的System.Web.Mvc.ActionResult News(Int32)

所以,我想如果我明确创建了没有id参数可选的路由,就像这样:

    routes.MapRoute( _
        "Default2", _
        "{controller}/{action}/{id}",
        New With {.controller = "Home", .action = "Index"},
        New With {.action = "^[a-zA-Z_]+$", .id = "\d{1,8}|"}
    )

    routes.MapRoute( _
        "Default", _
        "{controller}/{action}",
        New With {.controller = "Home", .action = "Index"},
        New With {.action = "^[a-zA-Z_]+$"}
    ) 

它会起作用,但它没有同样的错误。

现在我知道简单的解决方案是调用我的方法不同的东西,但我不想这样做。

我还在考虑创建一个属性来为ID方法添加前缀,检查ID是否存在,以及它是否不允许该方法,但我也无法使其工作。

任何帮助将不胜感激。 卡尔

2 个答案:

答案 0 :(得分:2)

您可以使用UrlParameter.Optional和可以为空的ID来解决此问题:

routes.MapRoute( _
    "Default2", _
    "{controller}/{action}/{id}",
    New With {.controller = "Home", .action = "Index", id = UrlParameter.Optional},
    New With {.action = "^[a-zA-Z_]+$", .id = "\d{1,8}|"}
)

Function News(ByVal id As Integer?) As ActionResult
    if id.HasValue then 
         ...
    else
        ...
    end if 
End Function

答案 1 :(得分:1)

问题仍然是,一旦它识别了要调用的动作的名称,MVC动作调用者就无法在两种方法之间进行选择,因为它不会分析请求以查看哪些参数可能< / em>被绑定。

在选择方法之前,不会发生参数绑定阶段;所以你必须给它们不同的名字 - 或者你可以使id参数成为可以为空的整数(并保持可选的id route参数为默认值),如果它是null,则简单地链接到另一个重载。

如果你这样做,一定要用NonActionAttribute来装饰非参数重载,这样动作调用者就不会感到困惑,或者确实把它变成私有/保护。

更新

根据我们的评论进行更新 - 如果重命名您的操作方法,则无需返回REST标准 - 您只需使您的路线更具体(我提前道歉 - VB.Net甚至不是我的第二语言! ):

<HttpGet()>
<ActionName("AllNews")>
Function News() As ActionResult 
End Function

<HttpGet()>
Function News(ByVal id As Integer) As ActionResult
End Function  

'-- route for single news item with constraint
routes.MapRoute(
  "News",
  "Markets/News/{id}",
  New With { .controller = "Markets", .action = "News" }, 
  New With { .id = "\d{1,8}" });

'-- route for the all news action method
routes.MapRoute(
  "AllNews",
  "Markets/News",
  New With { .controller = "Markets", .action = "AllNews" });

现在你必须使用明确的路由来定位两个动作方法,但是在相同的RESTful uri方案下。

所有我的MVC REST服务都倾向于使用更多这样的显式路由,原因与您尝试解决的原因完全相同。