web-dev-qa-db-ja.com

ASP.NET Core MVCでアクションメソッドの属性を読み取る方法

この記事 に基づいて、コントローラーとコントローラーのアクションでマークされている属性を処理できるASP.NET CoreのIActionFilter実装を作成しようとしています。コントローラーの属性の読み取りは簡単ですが、アクションメソッドで定義された属性を読み取る方法を見つけることができません。

私が今持っているコードは次のとおりです。

public sealed class ActionFilterDispatcher : IActionFilter
{
    private readonly Func<Type, IEnumerable> container;

    public ActionFilterDispatcher(Func<Type, IEnumerable> container)
    {
        this.container = container;
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        var attributes = context.Controller.GetType().GetCustomAttributes(true);

        attributes = attributes.Append(/* how to read attributes from action method? */);

        foreach (var attribute in attributes)
        {
            Type filterType = typeof(IActionFilter<>).MakeGenericType(attribute.GetType());
            IEnumerable filters = this.container.Invoke(filterType);

            foreach (dynamic actionFilter in filters)
            {
                actionFilter.OnActionExecuting((dynamic)attribute, context);
            }
        }
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        throw new NotImplementedException();
    }
}

私の質問は次のとおりです。ASP.NETCore MVCでアクションメソッドの属性を読み取るにはどうすればよいですか。

46
Steven

MethodInfo クラスを介してアクションのControllerActionDescriptorにアクセスできます。

public void OnActionExecuting(ActionExecutingContext context)
{
    var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
    if (controllerActionDescriptor != null)
    {
        var actionAttributes = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true);
    }
}

MVC 5 ActionDescriptor 属性へのアクセスを許可するICustomAttributeProviderインターフェイスの実装に使用されるクラス。何らかの理由で、これはASP.NET Core MVC ActionDescriptor クラスで削除されました。

57
Henk Mollema

Henk Mollemaのソリューションに基づいた元のGetCustomAttributesを模倣する拡張メソッドを作成しました。

    public static IEnumerable<T> GetCustomAttributes<T>(this Microsoft.AspNet.Mvc.Abstractions.ActionDescriptor actionDescriptor) where T : Attribute
    {
        var controllerActionDescriptor = actionDescriptor as ControllerActionDescriptor;
        if (controllerActionDescriptor != null)
        {
            return controllerActionDescriptor.MethodInfo.GetCustomAttributes<T>();
        }

        return Enumerable.Empty<T>();
    }

それが役に立てば幸い。

6
Axel Márquez

私のカスタム属性は、ActionFilterAttributeを継承しています。コントローラーに配置しましたが、必要のないアクションが1つあります。 AllowAnonymous属性を使用してそれを無視したいのですが、動作しません。そこで、このスニペットをカスタム属性に追加してAllowAnonymousを見つけてスキップします。 forループで他のものを取得できます。

    public class PermissionAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            foreach (var filterDescriptors in context.ActionDescriptor.FilterDescriptors)
            {
                if (filterDescriptors.Filter.GetType() == typeof(AllowAnonymousFilter))
                {
                    return;
                }
            }
        }
    }
5
MichaelMao

Henk Mollena による回答

public void OnActionExecuting(ActionExecutingContext context) { var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor; if (controllerActionDescriptor != null) { var controllerAttributes = controllerActionDescriptor .MethodInfo .GetCustomAttributes(inherit: true); } }

属性の存在を確認する場合は正しい方法ですアクションに適用

属性の存在を確認したい場合に備えて、彼の答えに追加したいだけですコントローラに適用

_public void OnActionExecuting(ActionExecutingContext context)
{
    var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
    if (controllerActionDescriptor != null)
    {
        var actionAttributes = controllerActionDescriptor.ControllerTypeInfo.GetCustomAttributes(inherit: true);
    }
}
_

また、GetCustomAttributes関数のオーバーロード関数を使用して、特定の属性を取得できます。

var specificAttribute = GetCustomAttributes(typeof(YourSpecificAttribute), true).FirstOrDefault()

0
Saurabh Pati