我正在使用AttributeRouting:http://attributerouting.net/
如果我有两个具有相同名称的操作,但GET的路由与POST的路由不同,为什么Url.Action
会生成与我的GET操作匹配的URL,即使我的操作方法也是如此指的是一个帖子?
我尝试将动词作为
传递Url.Action("CreateEdit", new { method = "POST" })
然而,这会返回字符串/enrollments/create
,而不是对应于POST的/enrollments/createedit
。
我不希望这种情况有效,但尝试使用这种技术时会尝试使用此技术:
Url.Action("CreateEdit", new { HttpMethodConstraint = new HttpMethodConstraint("POST") })
然而,这些都无法解决问题,而且网址仍然是我的GET路线。
我已经确认我可以发布到/enrollments/createedit
的硬编码网址,因此POST操作确实具有该路由,只是为了排除POST操作默认[POST]
的可能性违约到预期的路线。
问题是我通常会避免使用硬编码的网址,并使用Url.Action或Html.BeginForm(也会出现同样的问题),以便所有网址都来自行动路线。
以下是我定义行动的方式:
[GET("create")]
[GET("edit/{id:guid?}")]
public ActionResult CreateEdit(Guid? id)
...
[POST] //default to "createedit"
public ActionResult CreateEdit()
...
请注意,此问题与提出实际请求无关,而是生成路由网址。
如何向Url.Action表明它应该使用来自[POST]而不是GET的路线。没有带有约束或HTTP Verb的重载?请注意,Html.BeginForm在生成操作URL属性时会出现同样的问题,这显然是面向POST的方法。
如果我将行动路线简化为(虽然以上是我的目标路线),它也不起作用:
[GET("create")]
public ActionResult CreateEdit()
...
[POST("createedit")] //default to "createedit"
public ActionResult CreateEdit()
...
Url.Action("CreateEdit", new { method = "POST" })
返回" / enrollments / create"很明显,因为method = 'POST'
不是为Url.Action指定所需路线的正确方法。 有没有办法告诉Url.Action或Html.BeginForm指定需要POST路由? BeginForm的方法参数会影响method="post"
html属性,但action属性仍然是使用错误的/enrollments/create
网址生成。我看到area="Admin"
用于指定路线参数中的区域。是否有一些魔法属性可以添加来指定动词?如果没有,那么显然没有办法一致地获得正确的URL,如果我需要维护所需的路由,我可能需要重命名我的一个动作。我希望有一些路线值我可以将类似的添加到new { area = "SomeArea" }
。 method = "POST"
只是我对可能有效的猜测。
请求管道尊重路由约束,如果它们都是相同的路由,那么它可以正常工作。因此,如果两者都是[POST("creatededit")]
和[GET("create"]
,那么它将正常工作,因为两者的URL是相同的,然后当实际请求产生时,由于HttpMethodContraint而由管道进行区分。
如果我使用参数使路线不同,那么只有当我消除[GET("create")]
如果Url.Action没有已知/支持/记录的方式来获取路由属性,那么答案可能只是Url.Action没有任何方法可以告诉它所需的VERB。
Url.Action("SomeAction", new { area ="SomeArea" })
我不明白这是多么复杂。
我不问如何发出POST请求。我知道该怎么做,但我不打算将URL硬编码到我的视图中。这变成了维护的噩梦。
如果我的老板不在SOE上,我可以改变我的路线。所以我无法消除[GET(" create")]路线。我可以通过重命名这样的动作来解决:
[GET("create")]
[GET("edit/{id:guid?}")]
public ActionResult CreateEdit(Guid? id)
...
[POST("createedit")]
public ActionResult CreateEditPost()
...
这有点脏,但有效。它仍然没有回答这个问题。
如果有办法为Url.Action指定VERB,我认为答案将是一个有用的资源。也许不会像Url.Action("SomeAction", new { area ="SomeArea" })
那样多的人,但它会记录Url.Action的一个功能,对我来说这是难以捉摸的。也许它不支持它。也许我需要深入研究源代码。
答案 0 :(得分:2)
我在原来的答案中蠢蠢欲动。我并没有真正思考它,而且可能回答得太快了。以下是它归结为:
Url.Action
与控制器/动作样式路由非常相关。如果有两个匹配的操作(重载,其中一个是GET版本而另一个是POST),则URL 应该相同,因此返回GET或第一个版本。通过让您自定义面向外部的URL,参见AttributeRouting,而在内部,Url.Action
只是试图找到一条路径,让您进入所请求的操作。一旦找到匹配,它就会假定它已经足够好了,特别是在MVC5之前,它应该是。
MVC5引入属性路由作为一等公民,但从我所见,这个边缘情况(同一行为的GET和POST版本有不同的URL,你特别想要POST版本)没有被覆盖。
那就是说,我看到了几个可能的解决方法:
使用不同的操作名称。如果您的POST操作的名称类似于CreateEditPost
,那么您可以非常轻松地执行Url.Action("CreateEditPost")
并获取正确的网址。由于您的路线不会直接受到操作名称的影响,因此它的名称并不重要。
使用命名路由。如果您为路线命名,则可以使用Url.RouteUrl
代替您想要的路线。例如:
[POST("createedit", RouteName = "CreateEditPost")]
public ActionResult CreateEdit()
{
...
}
然后:
@Url.RouteUrl("CreateEditPost")