2010-04-15 2 views
6

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

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

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

ответ

5

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

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

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

(курсив мой)

Обратите внимание, что вы все равно можете использовать 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); 
    } 
} 
+0

Я знаю, что все еще * могу * использовать 'AcceptVerbs', но я думаю, что новые атрибуты выглядят намного лучше в коде, и надеялись, что команда MVC задумалась об этом при их реализации ... –

+0

@ Томас - к счастью, вы можете сделать свой собственный по мере необходимости. См. Мое обновление. – tvanfosson

0

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

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

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

+0

Причина, почему я спрашиваю, что я хотел бы, чтобы * как * POST и DELETE запросов, но не Другие. Я надеялся, что атрибуты будут работать как оператор набора UNION, а не оператор INTERSECTION ... Но вы не всегда можете получить то, что хотите. У вас есть источник этого поведения? –

+0

HttpPost и HttpDelete довольно распространены. Я ожидал бы, если вы ожидаете, что действие удаления будет работать как с использованием AJAX (Delete), так и без AJAX (Post), когда javascript отключен. – tvanfosson

+0

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

4

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

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

3

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

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

или

[AcceptVerbs("GET","POST")] 
public ActionResult Customers() { 
}