On Asp.net Web Api authorization filters, how can I access to parameters?

余生颓废 提交于 2019-12-03 00:44:09

The authorization attributes run before parameter binding has run therefore you cannot (as you have seen) use the ActionArguments collection. Instead you will need to use the request uri for query parameters and route data for uri parameters as demonstrated below.

//request at http://localhost/api/foo/id?MyValue=1
public class MyAuthorizationAttribute : AuthorizeAttribute
{
    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        //will not work as parameter binding has not yet run
        object value;
        actionContext.ActionArguments.TryGetValue("id", out value);

        //Will get you the resource id assuming a default route like /api/foo/{id} 
        var routeData = actionContext.Request.GetRouteData();
        var myId = routeData.Values["id"] as string;

        //uri is still accessible so use this to get query params
        var queryString = HttpUtility.ParseQueryString(actionContext.Request.RequestUri.Query);
        var myQueryParam = queryString["MyValue"];

        //and so on
    }
}

About the execution order:

There are 3 different ways of specifying the execution order of filters using the FilterScope Enumeration... scope being Global, Controller and Action. The AuthoriseAttribute is "Global" and therefore it

Specifies an action before Controller.

If you needed to specify the execution order within these 3 scopes then you should read this blog article here where you will need to implement a FilterProvider

To add some data to the pipe:

Use the properties collection on the request this collection is available for the duration of the request.

    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        actionContext.Request.Properties.Add("__MYKEY__","MyValue");

        //access this later in the controller or other action filters using
        var value = actionContext.Request.Properties["__MYKEY__"];

    }

Another alternative to get to the parameters is to Execute the binding for the parameters.

try
{
    var binding = actionContext.ActionDescriptor.ActionBinding;
    var parameters = binding.ParameterBindings.OfType<ModelBinderParameterBinding>();
    var newBinding = new HttpActionBinding(actionContext.ActionDescriptor, parameters.ToArray());
    newBinding.ExecuteBindingAsync(actionContext, new CancellationToken());
    var id = actionContext.ActionArguments["id"] as string;
}
catch
{
    base.HandleUnauthorizedRequest(actionContext);
}

Note: You need to make sure you only filter on the parameters that will come from the Request URI, as I have noticed that executing the binding for any parameters that are expected to come from the Request body will no longer be passed on to the actual action. i.e. those parameters will be null.

This is just to note that you can do this, I'd recommend using GetRouteData()/RouteData as it is not likely to disrupt the further flow of ASP.NET MVC modelbinding.

var routeData = actionContext.ControllerContext.RouteData;
var id = routeData.Values["id"] as string;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!