Как я могу перегрузить действия ASP.NET MVC на основе принятых глаголов HTTP?

Хотел использовать один и тот же URL-адрес для GET/PUT/DELETE/POST для API на основе REST, но когда единственное, что отличает действия, это то, какие HTTP-глаголы он принимает, он считает их дубликатами!

«Тип уже определяет элемент с именем «Индекс» с теми же типами параметров».

На что я сказал, ну и что? Этот принимает только GET, этот принимает только POST... должны быть в состоянии сосуществовать, верно?

Как?


person Ryan    schedule 14.06.2011    source источник
comment
вроде не по теме, но я делаю именно это с FubuMVC, стоит проверить, есть ли у вас возможность сделать это   -  person heisenberg    schedule 14.06.2011


Ответы (4)


Это не ограничение 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, чтобы узнать, как можно организовать ваши маршруты.

person Darin Dimitrov    schedule 14.06.2011
comment
разные глаголы также будут иметь разные параметры, можете ли вы уточнить? Я думал, что /users/[id] — это хороший URL-адрес, и он может одинаково принимать GET, POST, PUT, DELETE... единственная разница будет заключаться в содержании запроса, верно? - person Ryan; 14.06.2011
comment
@Ryan, нет, действие, которое будет отвечать на запрос POST, будет использовать модель представления, которую вы создаете, в качестве аргумента действия: [HttpPost]public ActionResult Foo(AModelToCreate model) { ... }, что, конечно, будет отличаться от действия GET, для которого потребуется только id. - person Darin Dimitrov; 14.06.2011
comment
ооо, мне нужно это прочитать, все, что я когда-либо использовал, это вытаскивание переменных из объекта запроса... - person Ryan; 14.06.2011
comment
@ Райан, оооооооооооооооооооооооооооооооооооооооооооооооооооооооооо к к этому. Вы никогда не должны извлекать переменные из Request. Как вы справляетесь с такими вещами, как проверка, вы вручную анализируете все эти строки в соответствующих типах моделей? Вот что такое привязка модели ASP.NET MVC, и она очень мощная. - person Darin Dimitrov; 14.06.2011

В то время как ASP.NET MVC позволит вам иметь два действия с одним и тем же именем, .NET не позволит вам иметь два метода с одной и той же сигнатурой, то есть с одним и тем же именем и параметрами.

Вам нужно будет назвать методы по-разному, используя атрибут ActionName, чтобы сообщить ASP.NET MVC, что на самом деле это одно и то же действие.

Тем не менее, если вы говорите о GET и POST, эта проблема, скорее всего, исчезнет, ​​так как действие POST будет принимать больше параметров, чем GET, и поэтому его можно будет различить.

Итак, вам нужно либо:

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

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

Or:

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

[HttpPost]
public ActionResult ActionName(string aParameter) {...}
person Thom    schedule 14.06.2011

Другой вариант — иметь единый метод, который принимает все и различает 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));
            }
person The Coder    schedule 03.06.2012
comment
Умное использование HttpMethod, но нарушает SRP. - person Rap; 17.07.2012

В качестве обходного пути вы можете добавить к одному из методов дополнительный аргумент со значением по умолчанию, просто чтобы обойти ограничение и получить возможность сборки.

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

person yoel halb    schedule 23.01.2013