WebApi iActionFilter实现。如何阅读自定义控制器属性?

时间:2018-11-28 00:37:51

标签: c# asp.net-web-api

我正在实现自定义身份验证过滤器,并使用此处描述的“被动属性”方法: http://blog.ploeh.dk/2014/06/13/passive-attributes/

DI可以按预期工作,但是我不知道如何从控制器本身读取自定义属性?我希望单个动作和整个控制器都支持此功能。

控制器示例:

[TokenAuth] // This attribute not "visible"
public class SupportController : ApiController
{
    private ISecurityService SecurityService { get; }

    public SupportController(ISecurityService securityService)
    {
        this.SecurityService = securityService;
    }

    [TokenAuth] // This attribute works
    [HttpGet]
    public object StartupData()
    {
        return "Startup data";
    }
}

这是我读取自定义属性的过滤器代码的一部分:

public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
    var tokenAuthAttribute = actionContext.ActionDescriptor.GetCustomAttributes<TokenAuthAttribute>(true).SingleOrDefault();

    // This line below exists unless attribute placed on method/action

    if (tokenAuthAttribute == null) return continuation();

    var req = actionContext.Request;

有什么方法可以访问控制器的属性?

2 个答案:

答案 0 :(得分:2)

动作描述符应使您可以通过ControllerDescriptor属性访问控制器类型

var actionDescriptor = actionContext.ActionDescriptor;

var tokenAuthAttribute = 
    actionDescriptor.GetCustomAttributes<TokenAuthAttribute>(true).SingleOrDefault() ??
    actionDescriptor.ControllerDescriptor.GetCustomAttributes<TokenAuthAttribute>(true).SingleOrDefault();

//...

上面的代码首先检查动作描述符,如果没有发现,则检查控制器描述符。

答案 1 :(得分:0)

这是一个完整的抽象类,其中的属性作为通用参数。您可以从中继承,指定属性,然后覆盖ExecuteFilterBehavior。这将检查控制器和方法上的属性。您可以将其修改为仅执行其中一项。

public abstract class ActionFilterBehaviorBase<TAttribute> : IActionFilter where TAttribute : Attribute
{
    public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
    {
        if (ControllerHasAttribute(actionContext) || ActionHasAttribute(actionContext))
        {
            return ExecuteFilterBehavior(actionContext, cancellationToken, continuation);
        }
        return continuation();
    }

    protected abstract Task<HttpResponseMessage>  ExecuteFilterBehavior(HttpActionContext actionContext, CancellationToken cancellationToken,
        Func<Task<HttpResponseMessage>> continuation);

    public virtual bool AllowMultiple { get; } = false;

    private bool ControllerHasAttribute(HttpActionContext actionContext)
    {
        return actionContext
                .ControllerContext.Controller.GetType()
                .GetCustomAttributes(false)
                .Any(attribute => attribute.GetType().IsAssignableFrom(typeof(TAttribute)));
    }

    private bool ActionHasAttribute(HttpActionContext actionContext)
    {
        return actionContext
            .ActionDescriptor
            .GetCustomAttributes<TAttribute>()
            .Any();
    }
}

更多详细信息here