Как работают атрибуты httppost, httpput и т. д. в ASP.NET MVC 2?

В ASP.NET MVC 2 было введено несколько новых атрибутов фильтра действий в качестве «сокращения» для атрибутов в ASP.NET MVC 1; например, применение HttpPostAttribute делает то же самое, что и применение [AcceptVerbs(HttpVerbs.Post)] к методу действия.

Кроме того, с более подробным синтаксисом можно комбинировать разные методы, чтобы разрешить, например, как Post, так и Delete.

Теперь мне интересно: как работают новые атрибуты? Если я применю и [HttpPost], и [HttpDelete], будет ли ASP.NET MVC 2 разрешать оба или требовать оба (таким образом, ничего не разрешая)?


person Tomas Aschan    schedule 15.04.2010    source источник


Ответы (4)


Глядя на код для ActionMethodSelector, кажется, что все атрибуты метода действия должны возвращать значение true для IsValidForRequest, прежде чем это действие будет добавлено в набор возможных методов сопоставления. Поскольку HttpPost и HttpDelete не могут вернуть IsValidForRequest для одного и того же запроса, я ожидаю, что использование обоих предотвратит совпадение этого действия с любым запросом.

Вот красноречивый комментарий из кода:

private static List RunSelectionFilters(...) {
// удалить все методы, которые отказываются от этого запроса
// чтобы отказаться, по крайней мере один атрибут, определенный в методе, должен возвращать false

(выделено мной)

Обратите внимание, что вы по-прежнему можете использовать AcceptVerbs и явно ИЛИ глаголы, если вам нужно совпадать.

EDIT — вот вам атрибут HttpPostOrDelete.

[AttributeUsage( AttributeTargets.Method, AllowMultiple = false, Inherited = false )]
public class HttpPostOrDeleteAttribute : ActionMethodSelectorAttribute
{
    private static readonly AcceptVerbsAttribute _innerPostAttribute = new AcceptVerbsAttribute( HttpVerbs.Post );
    private static readonly AcceptVerbsAttribute _innerDeleteAttribute = new AcceptVerbsAttribute( HttpVerbs.Delete );

    public override bool IsValidForRequest( ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo )
    {
        return _innerDeleteAttribute.IsValidForRequest( controllerContext, methodInfo )
               || _innerPostAttribute.IsValidForRequest( controllerContext, methodInfo );
    }
}
person tvanfosson    schedule 15.04.2010
comment
Я знаю, что все еще могу использовать AcceptVerbs, но я думаю, что новые атрибуты выглядят намного лучше в коде, и я надеялся, что команда MVC подумала об этом при их реализации... - person Tomas Aschan; 16.04.2010
comment
@ Томас - к счастью, вы можете сделать свой собственный по мере необходимости. Смотрите мое обновление. - person tvanfosson; 16.04.2010

Все без исключения фильтры в MVC независимы друг от друга. Никакие фильтры не имеют особого случая нигде в структуре MVC. Это было преднамеренным дизайнерским решением, чтобы компоненты инфраструктуры MVC, такие как вызывающая программа, не могли «обманывать» и обрабатывать фильтры, расположенные в двоичном файле MVC, иначе, чем фильтры, которые вы, как разработчик приложения, написали бы.

Поэтому, когда вызывающая сторона видит [HttpGet] и [HttpPost] в одном и том же методе, нет специального кода для их объединения. Они выполняются независимо. И поскольку они никогда не могут возвращать значение true для одного и того же запроса, [HttpGet, HttpPost] фактически исключает любой конкретный метод из числа методов действия.

person Levi    schedule 15.04.2010

Вы можете использовать AcceptVerbs для цепочки, например:

[AcceptVerbs(HttpVerbs.Get|HttpVerbs.Post)]
public ActionResult Customers() {
}

or

[AcceptVerbs("GET","POST")]
public ActionResult Customers() {
}
person Ankur Bulsara    schedule 23.10.2010

Если вы поместите [HttpPost] и [HttpDelete] вместе, я думаю, потребуются оба (что невозможно). Если цепочку [HttpGet] тоже не будет работать и т.д...

Вы можете легко проверить это, просто взяв существующий метод действия [HttpPost] и добавив к нему [HttpDelete]. Пост перестанет работать.

Я не нашел примеров, где мне нужно было бы связать их, как вы предлагаете.

person Kelsey    schedule 15.04.2010
comment
Причина, по которой я спрашиваю, заключается в том, что я хотел бы разрешить оба запросы POST и DELETE, но не другие. Я надеялся, что атрибуты будут работать как оператор множества UNION, а не как оператор INTERSECTION... Но ведь не всегда можно получить то, что хочешь. У вас есть где-нибудь источник такого поведения? - person Tomas Aschan; 16.04.2010
comment
HttpPost и HttpDelete довольно распространены. Я ожидаю, что действие удаления будет работать как с использованием AJAX (удаление), так и без AJAX (Post), когда javascript отключен. - person tvanfosson; 16.04.2010
comment
На самом деле я попробовал тест и не смог найти никаких комбинаций, в которых я мог бы заставить работать связанный атрибут, такой как ваш пример. Я взял рабочие методы и просто добавил к ним атрибуты, и, конечно же, это сломало их все. - person Kelsey; 16.04.2010