ASP.NET MVC 路由 Rest 标准 URL 参数

发布于 2024-11-16 22:50:48 字数 1151 浏览 4 评论 0原文

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

我有以下控制器操作:

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

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

我希望它是智能的,如果 url 中没有 ID,则转到第一个,如果有,则转到第二个。

我收到以下错误:

当前对控制器类型“MarketsController”上的操作“News”的请求不明确>以下操作方法之间: 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 是否存在,如果不存在则不允许该方法,但我也无法让它工作。

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

Having a bit of a nightmare, hopefully I'm just being stupid.

I have the following controller actions:

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

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

I want it to be smart, and go to the first if I have no ID in the url, and the second if there is.

I got the following error:

The current request for action 'News' on controller type 'MarketsController' is ambiguous >between the following action methods:
System.Web.Mvc.ActionResult News() on type TradeChaseMVC.MarketsController
System.Web.Mvc.ActionResult News(Int32) on type TradeChaseMVC.MarketsController

So, I thought if i explicitly created routes without the id parameter optional, like this:

    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_]+$"}
    ) 

It would work, but it doesn't same error.

Now I know the simple solution is to call my methods different things, but i don't want to do this.

I was also thinking of creating an attribute to prefix the ID method, to check for ID being there, and if it isn't dont allow that method, but I can't get this to work either.

Any help would be appreciated.
Karl

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

_畞蕅 2024-11-23 22:50:48

您可以使用 UrlParameter.Optional 和可为 null 的 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

You can solve this usring UrlParameter.Optional and nullable 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
魂归处 2024-11-23 22:50:48

不,问题仍然是,一旦确定了要调用的操作的名称,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 服务都倾向于使用许多像这样的更明确的路由,其原因与您试图解决的原因完全相同。

No the problem is still that once it identifies the name of the action to be called, the MVC action invoker can't choose between the two methods because it doesn't analyse the request to see which parameters might be bound.

The parameter binding stage doesn't occur until the method is selected; so you are going to have to give them different names - or you could make the id parameter a nullable integer (and keep the optional id route parameter as default) and simply chain to the other overload if it comes in null.

If you do this, be sure to decorate the non-parameter overload with the NonActionAttribute so the action invoker doesn't get confused or, indeed, make it private/protected.

Update

An update following our comments - you don't have to go back on REST standards if you rename your action method - you just make your routes more specific (I apologise in advance - VB.Net is not even my second language!):

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

Now you have to explicit routes that target the two action methods but under the same RESTful uri scheme.

All my MVC REST services tend to use many more explicit routes like this for the exact same reason that you're trying to solve.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文