2011-06-14 135 views
23

希望对基于REST的API使用GET/PUT/DELETE/POST的相同URL,但是当Actions与它不同的唯一不同是它接受哪个HTTP动词时,它认为它们是重复的!如何基于接受的HTTP动词重载ASP.NET MVC动作?

“类型已经使用相同的参数类型定义了一个名为'Index'的成员。”

我说过,那又怎么样?这个只接受GET,这个只接受POST ......应该可以共存吗?

怎么样?

+1

一种偏离主题,但我正在用FubuMVC做这件事,值得检查一下,如果你有这样的自由 – heisenberg 2011-06-14 18:47:47

回答

35

这不是ASP.NET MVC限制或任何。它是.NET以及类是如何工作的:无论你如何努力,都不能在同一个类中使用两个具有相同名称的方法,它们采用相同的参数。你可以欺骗使用[ActionName]属性:

[HttpGet] 
[ActionName("Foo")] 
public ActionResult GetMe() 
{ 
    ... 
} 

[HttpPut] 
[ActionName("Foo")] 
public ActionResult PutMe() 
{ 
    ... 
} 

[HttpDelete] 
[ActionName("Foo")] 
public ActionResult DeleteMe() 
{ 
    ... 
} 

[HttpPost] 
[ActionName("Foo")] 
public ActionResult PostMe() 
{ 
    ... 
} 

当然,在一个真正的RESTful应用程序不同的动词会采取不同的参数,以及,所以你很少有这样的情况。

您可以查看SimplyRestful了解关于如何组织您的路线的一些想法。

+0

“不同的动词也会采用不同的参数”,你能详细说明吗?我认为/ users/[id]是一个很好的URL,可以接受GET,POST,PUT,DELETE都一样...唯一的区别是请求的内容,对吗? – BigOmega 2011-06-14 19:05:51

+0

@Ryan,不,一个会响应POST请求的动作会把你正在创建的视图模型作为动作参数:'[HttpPost] public ActionResult Foo(AModelToCreate model){...}'这当然是不同于只需要'id'的GET操作。 – 2011-06-14 19:08:24

+0

ohhh我需要读进去,我曾经使用的是从Request对象中取出变量... – BigOmega 2011-06-14 19:12:22

8

虽然ASP.NET MVC将允许您有两个具有相同名称的动作,但.NET不允许您拥有两个具有相同签名的方法 - 即具有相同的名称和参数。

您将需要使用ActionName属性以不同方式命名方法以告诉ASP.NET MVC它们实际上是相同的操作。

这就是说,如果你在谈论一个GETPOST,这个问题可能会消失,因为POST行动将采取比GET更多的参数,因此可以区分的。

所以,你需要两种:

[HttpGet] 
public ActionResult ActionName() {...} 

[HttpPost, ActionName("ActionName")] 
public ActionResult ActionNamePost() {...} 

或者:

[HttpGet] 
public ActionResult ActionName() {...} 

[HttpPost] 
public ActionResult ActionName(string aParameter) {...} 
1

另一种选择是有一个接受所有和之间的区别列举HTTPMethod,并从那里调用相应的代码,一个方法。例如。

  string httpMethod = Request.HttpMethod.ToUpperInvariant(); 

      switch (httpMethod) 
      { 
       case "GET": 
        return GetResponse(); 

       case "POST": 
        return PostResponse(); 

       default: 
        throw new ApplicationException(string.Format("Unsupported HttpMethod {0}.", httpMethod)); 
      } 
+2

巧妙使用HttpMethod,但违反了SRP。 – Rap 2012-07-16 22:07:14

0

作为一种解决方法,您可以向其中一个方法添加一个带有默认值的额外参数,只是为了绕过限制并能够构建。

当然要记住,这不是最推荐的做事方式,而且你必须在你的代码中(通过参数名或通过注释)明确这是一个额外的参数,只是为了允许它来构建,当然,确保你已经正确地修饰了你的属性。