Как я могу перегрузить действия ASP.NET MVC на основе принятых HTTP-глаголов?
Хотел использовать тот же URL-адрес для GET/PUT/DELETE/POST для API на основе REST, но когда единственное, что отличается в действиях, это то, какие HTTP-глаголы он принимает, он считает их дублирующимися!
"Тип уже определяет член с именем" Индекс "с такими же типами параметров".
На что я сказал, и что? Этот принимает только GET, этот принимает только POST... должен быть в состоянии сосуществовать правильно?
Как?
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, чтобы узнать, как организовать ваши маршруты.
В то время как 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) {...}
Другой вариант - иметь единственный метод, который принимает все и различает 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));
}
В качестве обходного пути вы можете добавить к одному из методов дополнительный аргумент со значением по умолчанию, просто чтобы обойти ограничение и иметь возможность строить.
Конечно, имейте в виду, что это не самый рекомендуемый способ выполнения действий, а также вы должны будете четко указать в своем коде (по имени параметра или через комментарии), что это дополнительный аргумент, позволяющий его строить, и, конечно же, убедитесь, что вы правильно украсили свои атрибуты.