2012-03-04 3 views
65

Почему это неправильно?Методы GET и POST с тем же именем действия в том же контроллере

{ 
    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(); 
     } 

    } 

Как я могу иметь controlller РВП ответ одно, когда «getted» и один, когда «размещена»?

ответ

130

Поскольку вы не можете иметь два метода с тем же именем и подписью вы должны использовать ActionName атрибут:

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

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

Также см "How a Method Becomes An Action"

+0

Я знаю его слишком поздно, чтобы спросить. но возможно ли иметь два разных метода действия HttpPost с тем же именем, которые принимают разные параметры. Я говорю о случае, когда мне нужно применить фильтры к методу create, который уже имеет метод HttpPost, определенный – Vini

+0

Да, это возможно, потому что это действительная подпись метода .Net. Методы перегружены (перегрузка метода). – nwolisa

2

Может не много действий и то же имя и тот же параметр

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

, хотя int int id не используется

+1

Будет ли это действительно работать, если id является непустым значением int? – jahu

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

} 
32

Хотя 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) {...} 
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

Если вы не хотите, зависимость от пакетов AttributeRouting вы могли бы сделать это, написав селектор пользовательских действий атрибут.

12

Мне нравится принимать форму сообщения для моих действий POST, даже если мне это не нужно. Для меня это просто похоже на то, что нужно делать, поскольку вы якобы размещаете что-то.

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

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

Простое замечательное объяснение – Ali

+1

Только проблема заключается в том, что это вызывает взломанное исключение HttpRequestValidationException, даже если [AllowHtml] и т. Д. Не то, чтобы это было плохое исключение, но его реализация и когда она запускается (и особенно когда она запускается в области) неоправданно непрозрачный. – Ted

1

Вы получили хороший ответ на этот вопрос, но я хочу добавить свои два цента. Вы можете использовать один метод и запросы процесса в соответствии с типом запроса:

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(); 
} 
Смежные вопросы