如何根据接受的HTTP动词重载ASP.NET MVC操作?

23

希望在REST API的GET/PUT/DELETE/POST请求中使用相同的URL,但当不同HTTP方法是Action唯一不同的时候,它会认为它们是重复的!

"该类型已经定义了一个成员名为'Index',具有相同的参数类型。"

我想说,那又怎样?这一个只接受GET请求,那一个只接受POST请求...应该能够共存才对吧?

如何实现呢?


1
有些离题,但我正在使用 FubuMVC 进行类似的操作,如果你有自由的话,值得一试。 - heisenberg
4个回答

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,了解如何组织路由的一些想法。

不同的动词也会带有不同的参数。你能详细说明一下吗?我认为/users/[id]是一个很好的URL,可以接受GET、POST、PUT、DELETE请求,只是请求内容不同而已,对吧? - MetaGuru
@Ryan,不,响应POST请求的操作将以您正在创建的视图模型作为操作参数:[HttpPost]public ActionResult Foo(AModelToCreate model) { ... },这当然与只需要一个id的GET操作不同。 - Darin Dimitrov
哦,我需要深入了解一下,我所使用的只是从请求对象中提取变量... - MetaGuru
@Ryan,噢噢噢噢噢噢噢噢噢噢噢噢,你绝对需要深入了解一下。你不应该从“Request”中提取变量。你是如何处理验证的?你是手动将所有这些字符串解析为它们各自的模型类型吗?这就是ASP.NET MVC模型绑定的全部内容,它非常强大。 - Darin Dimitrov

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

0

作为一种解决办法,你可以在其中一个方法中添加一个带有默认值的额外参数,以绕过限制并能够进行构建。

当然要记住,这不是最推荐的做法,你还需要在代码中明确说明(通过参数名称或注释),这是一个额外的参数仅用于允许构建,并且当然要确保你已经正确地装饰了属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接