在同一控制器中具有相同动作名称的GET和POST方法[重复]


78

为什么这不正确?

{
    public class HomeController : Controller
    {

        [HttpGet]
        public ActionResult Index()
        {
            Some Code--Some Code---Some Code
            return View();
        }

        [HttpPost]
        public ActionResult Index()
        {
            Some Code--Some Code---Some Code
            return View();
        }

    }

当“被获取”时,我如何让控制者回答一件事?当“发布”时,我该如何回答?

Answers:


173

由于不能有两个具有相同名称和签名的方法,因此必须使用ActionName属性:

[HttpGet]
public ActionResult Index()
{
  // your code
  return View();
}

[HttpPost]
[ActionName("Index")]
public ActionResult IndexPost()
{
  // your code
  return View();
}

另请参阅“方法如何成为动作”


我知道来不及了。但是有可能具有相同名称的两个不同的HttpPost操作方法采用不同的参数。我说的是我需要将过滤器应用于已经定义了HttpPost方法的create方法的情况
Vini 2015年

是的,有可能,因为它是有效的.Net方法签名。方法已重载(方法重载)。
nwolisa

37

虽然ASP.NET MVC允许您使用相同的名称进行两个操作,但是.NET不允许您使用具有相同签名的两个方法-即相同的名称和参数。

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

就是说,如果您正在谈论GET和POST,则此问题可能会消失,因为POST操作将使用比GET更多的参数,因此可以区分。

因此,您需要:

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

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

要么,

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

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

1
例如,GET和POST的Delete操作都需要一个ID。GET用于查看数据,而POST用于删除数据。在这种情况下,我需要使用ActionName
Xeuron

17

我喜欢接受POST操作的表单发布,即使我不需要它。对我来说,感觉就像是在做正确的事情,因为您应该发布一些东西

public class HomeController : Controller
{
    public ActionResult Index()
    {
        //Code...
        return View();
    }

    [HttpPost]
    public ActionResult Index(FormCollection form)
    {
        //Code...
        return View();
    }
}

1
唯一的问题是,即使[AllowHtml]等,它也会触发爆炸的HttpRequestValidationException。这并不是一个坏异常,但是它的实现以及它的触发时间(尤其是在区域中触发时)是不必要的不​​透明。
Ted

5

为了回答您的特定问题,在一个类中不能有两个具有相同名称和相同参数的方法。使用HttpGet和HttpPost属性不会区分方法。

为了解决这个问题,我通常会包括您要发布的表单的视图模型:

public class HomeController : Controller
{
    [HttpGet]
    public ActionResult Index()
    {
        Some Code--Some Code---Some Code
        return View();
    }

    [HttpPost]
    public ActionResult Index(formViewModel model)
    {
        do work on model --
        return View();
    }

}

3

您对这个问题的回答很好,但是我要加两分钱。您可以使用一种方法并根据请求类型处理请求:

public ActionResult Index()
{
    if("GET"==this.HttpContext.Request.RequestType)
    {
        Some Code--Some Code---Some Code for GET
    }
    else if("POST"==this.HttpContext.Request.RequestType)
    {
        Some Code--Some Code---Some Code for POST
    }
    else
    {
        //exception
    }

    return View();
}

2

不能多重操作相同名称和相同参数

    [HttpGet]
    public ActionResult Index()
    {
        return View();
    }
    [HttpPost]
    public ActionResult Index(int id)
    {
        return View();
    }

虽然没有使用int id


2

您不能有多个具有相同名称的操作。您可以将参数添加到一种方法中,这将是有效的。例如:

    public ActionResult Index(int i)
    {
        Some Code--Some Code---Some Code
        return View();
    }

有几种方法可以使动作仅因请求动词而不同。我最喜欢且最容易实现的是使用AttributeRouting包。安装完成后,只需向您的方法添加一个属性,如下所示:

  [GET("Resources")]
  public ActionResult Index()
  {
      return View();
  }

  [POST("Resources")]
  public ActionResult Create()
  {
      return RedirectToAction("Index");
  }

在上面的示例中,方法具有不同的名称,但是两种情况下的操作名称均为“ Resources”。唯一的区别是请求动词。

可以使用NuGet这样安装软件包:

PM>安装包属性路由

如果您不希望依赖AttributeRouting包,则可以通过编写自定义操作选择器属性来实现。


0

今天,我正在检查有关同一问题的一些资源,并且得到了一个非常有趣的示例。

可以通过GET和POST协议调用相同的方法,但是您需要像这样重载参数:

@using (Ajax.BeginForm("Index", "MyController", ajaxOptions, new { @id = "form-consulta" }))
{
//code
}

那个行动:

[ActionName("Index")]
public async Task<ActionResult> IndexAsync(MyModel model)
{
//code
}

默认情况下,没有显式协议的方法是GET,但是在那种情况下,有一个声明的参数允许该方法像POST一样工作。

执行GET时,该参数无关紧要,但是执行POST时,根据您的请求需要该参数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.