Методи 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();
        }

    }

Як я можу отримати контролер, який відповідає на одне, коли його "отримують", а на другий, коли "відправляють"?

Відповіді:


176

Оскільки у вас не може бути двох методів з однаковим іменем та підписом, вам доведеться використовувати ActionNameатрибут:

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

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

Також див. "Як метод стає дією"


я знаю, що пізно запитувати. але чи можна мати два різні методи дії HttpPost з однаковим іменем, які приймають різні параметри. Я говорю про випадок, коли мені потрібно застосувати фільтри до методу створення, який вже має визначений метод HttpPost
Віні

Так, це можливо, оскільки це дійсний підпис методу .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 потрібен ідентифікатор. 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
Проблема лише в тому, що це запускає вибухоне вимкнення HttpRequestValidationException, навіть якщо [AllowHtml] тощо. Не те, що це поганий виняток, але його реалізація, і коли вона спрацьовує (і особливо, коли вона запускається в певній області), є надто непрозорою.
Тед,

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

У наведеному вище прикладі методи мають різні назви, але ім'я дії в обох випадках - "Ресурси". Єдина відмінність - дієслово запиту.

Пакет можна встановити за допомогою NuGet наступним чином:

PM> Маршрутизація атрибутів Install-Package

Якщо вам не потрібна залежність від пакетів 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, параметр потрібно на ваш запит.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.