0

做了一个噩梦,希望我只是愚蠢。

我有以下控制器操作:

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

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

我希望它聪明一点,如果我在 url 中没有 ID,则转到第一个,如果有,则转到第二个。

我收到以下错误:

当前对控制器类型“MarketsController”的操作“新闻”的请求在以下操作方法之间不明确 > 在以下操作方法中: System.Web.Mvc.ActionResult News() on type TradeChaseMVC.MarketsController System.Web.Mvc.ActionResult News(Int32) on输入 TradeChaseMVC.MarketsController

所以,我想如果我明确地创建了没有可选 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 是否存在,如果它不允许该方法,但我也无法让它工作。

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

4

2 回答 2

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
于 2011-06-21T12:42:29.033 回答
1

不,问题仍然在于,一旦它确定了要调用的动作的名称,MVC 动作调用程序就无法在这两种方法之间进行选择,因为它不会分析请求以查看可能绑定的参数。

在选择方法之前不会发生参数绑定阶段;所以你将不得不给他们不同的名字——或者你可以将id参数设为一个可为空的整数(并将可选的 id 路由参数保持为默认值),如果它为空,则简单地链接到另一个重载。

如果您这样做,请务必使用 装饰非参数重载,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 服务都倾向于使用更多像这样的显式路由,原因与您尝试解决的原因完全相同。

于 2011-06-21T12:18:01.143 回答