Как я могу перегрузить ASP.NET MVC Actions на основе принятых HTTP-глаголов?
Требуется использовать тот же URL-адрес для GET/PUT/DELETE/POST для API на основе REST, но когда единственное, что отличается от действий, - это то, какие HTTP-глаголы он принимает, он считает их дублирующими!
"Тип уже определяет член с именем" Index "с теми же параметрами."
На что я сказал, ну и что? Этот только принимает GET, этот только принимает POST... должен быть в состоянии сосуществовать правильно?
Как?
Ответы
Ответ 1
Это не ограничение 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 для некоторых идей о том, как ваши маршруты могут быть организованы.
Ответ 2
Хотя ASP.NET MVC позволит вам иметь два действия с тем же именем,.NET не позволит вам иметь два метода с одной и той же сигнатурой - то есть с тем же именем и параметрами.
Вам нужно будет указать методы по-разному с помощью атрибута ActionName
, чтобы сообщить ASP.NET MVC, что они фактически являются тем же самым действием.
Тем не менее, если вы говорите о GET
и a POST
, эта проблема, скорее всего, исчезнет, так как действие POST
будет принимать больше параметров, чем GET
, и поэтому может быть различимым.
Итак, вам нужно:
[HttpGet]
public ActionResult ActionName() {...}
[HttpPost, ActionName("ActionName")]
public ActionResult ActionNamePost() {...}
Или:
[HttpGet]
public ActionResult ActionName() {...}
[HttpPost]
public ActionResult ActionName(string aParameter) {...}
Ответ 3
Другой вариант - иметь единственный метод, который принимает все и различает 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));
}
Ответ 4
В качестве обходного пути вы можете добавить к одному из методов дополнительный аргумент со значением по умолчанию, просто чтобы обойти ограничение и иметь возможность создавать.
Конечно, имейте в виду, что это не самый рекомендуемый способ делать что-то, а также вам нужно будет прояснить в своем коде (по имени параметра или через комментарии), что это дополнительный аргумент, чтобы это разрешить и, конечно же, убедитесь, что вы правильно украсили свои атрибуты.