开发者

How do the httppost, httpput etc attributes in ASP.NET MVC 2 work?

开发者 https://www.devze.com 2022-12-27 14:54 出处:网络
In ASP.NET MVC 2, a couple of new action filter attributes were introduced, as \"shorthand\" for attributes in ASP.NET MVC 1; for example, app开发者_开发问答lying the HttpPostAttribute does the same t

In ASP.NET MVC 2, a couple of new action filter attributes were introduced, as "shorthand" for attributes in ASP.NET MVC 1; for example, app开发者_开发问答lying the HttpPostAttribute does the same thing as applying [AcceptVerbs(HttpVerbs.Post)] to an action method.

In addition, with the more verbose syntax, it is possible to combine different methods, in order to allow for example both Post and Delete.

Now I'm wondering: how do the new attributes work? If I apply both [HttpPost] and [HttpDelete], will ASP.NET MVC 2 allow both or require both (thus allowing nothing)?


Looking at the code for ActionMethodSelector, it appears that all action method attributes must return true for IsValidForRequest before that action will be added to the set of possible matching methods. Since it's not possible for HttpPost and HttpDelete to return IsValidForRequest for the same request, I would expect that using both will prevent that action from ever matching any request.

Here's a telling comment from the code:

private static List RunSelectionFilters(...) {
// remove all methods which are opting out of this request
// to opt out, at least one attribute defined on the method must return false

(emphasis mine)

Note that you can still use AcceptVerbs and explicitly OR the verbs if you need to match either.

EDIT -- here's an HttpPostOrDelete attribute for you.

[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 );
    }
}


All filters in MVC are - without exception - independent of one another. No filter is special-cased anywhere in the MVC framework. This was an intentional design decision so that MVC framework components like the invoker can't "cheat" and treat filters located in the MVC binary any differently than filters that you as an application developer would have written.

So when the invoker sees [HttpGet] and [HttpPost] on the same method, there's no special-casing code to take the union of the two. They're executed independently. And since they can never return true for the same request, [HttpGet, HttpPost] effectively excludes any particular method from being an action method.


You can use AcceptVerbs for chaining, e.g.:

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

or

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


If you put [HttpPost] and [HttpDelete] together it will require both (which isn't possible) I think. If you chain [HttpGet] it won't work either, etc...

You can easily test it my just taking an existing [HttpPost] action method and adding [HttpDelete] to it. The post will stop working.

I haven't found any examples where I would need to chain them like your suggesting though.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号