Search code examples
asp.net-mvcauthorizationmodel-bindingaction-filter

Why model binding happens earlier than filters


After going this excellent blog post by Simon I came to know that model binding happens earlier than filters execution (even before authorization filters). If the request is not authorized then it should be rejected as earlier as possible and in that case I prefer running the authorization filters before the model binding process. Also, by this way we could save the time avoiding scanning the request, creating model instances and performing validation.

Is there any reason that I simply don't understand why the MVC request processing pipeline is designed such a way that the model binding should happen before filters?


Solution

  • In asp.net mvc3, the authorization filters execute before the model binding, not after (see code below).

    Model binding occurs before the filters because the ActionExecutingContext (parameter of IActionFilter.OnActionExecuting) contains the action's parameters. Maybe they should have lazy loaded those parameters.

    The following code is from the System.Web.Mvc.ControllerActionInvoker.

    public virtual bool InvokeAction(ControllerContext controllerContext, string actionName) 
    {
        // code removed for brevity
        try 
        {
            // Notice the authorization filters are invoked before model binding
            AuthorizationContext authContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
            if (authContext.Result != null) {
                // the auth filter signaled that we should let it short-circuit the request
                InvokeActionResult(controllerContext, authContext.Result);
            }
            else {
                if (controllerContext.Controller.ValidateRequest) {
                    ValidateRequest(controllerContext);
                }
                // GetParameterValues does the model binding
                IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);
                ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);
                InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, postActionContext.Result);
            }
        }
        // code removed for brevity
    }