检索动作签名自定义属性

Bre*_*ias 3 c# reflection asp.net-web-api

假设我有一个如下所示的操作方法:

    [return: Safe]
    public IEnumerable<string> Get([Safe] SomeData data)
    {
        return new string[] { "value1", "value2" };
    }
Run Code Online (Sandbox Code Playgroud)

[安全]属性是我创建的自定义属性。我想创建一个ActionFilter来在参数或返回类型上定位[Safe]属性。我已经可以使用OnActionExecuting覆盖中的参数进行此操作,因为可以像这样访问我的[Safe]属性:

//actionContext is of type HttpActionContext and is a supplied parameter.
foreach (var parm in actionContext.ActionDescriptor.ActionBinding.ParameterBindings)
{
    var safeAtts = parm.Descriptor.GetCustomAttributes<SafeAttribute>().ToArray();
}
Run Code Online (Sandbox Code Playgroud)

但是,如何检索放置在返回类型上的[Safe]属性?

通过这种方法可能需要探索一些东西:

ModelMetadataProvider meta = actionContext.GetMetadataProvider();
Run Code Online (Sandbox Code Playgroud)

但是,如果这样做确实有效,则尚不清楚如何使其与一起使用ModelMetadataProvider

有什么建议么?

Iro*_*eek 5

尝试将ActionDescriptor属性从转换HttpActionContextReflectedHttpActionDescriptor第一个。然后使用该MethodInfo属性通过其ReturnTypeCustomAttributes属性检索自定义属性。

public override void OnActionExecuting(HttpActionContext actionContext)
{
  ...
  var reflectedActionDescriptor = actionContext.ActionDescriptor as ReflectedHttpActionDescriptor;
  if (reflectedActionDescriptor != null)
  {
    // get the custom attributes applied to the action return value
    var attrs = reflectedActionDescriptor
                  .MethodInfo
                  .ReturnTypeCustomAttributes
                  .GetCustomAttributes(typeof (SafeAttribute), false)
                  .OfType<SafeAttribute>()
                  .ToArray();
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

更新:启用跟踪

似乎的具体类型ActionDescriptor取决于Global Web API Services是否包含的实例ITraceWriter(请参阅:ASP.NET Web API中的跟踪)。

默认情况下,ActionDescriptor将为类型ReflectedHttpActionDescriptor。但是,启用跟踪后(通过调用config.EnableSystemDiagnosticsTracing()),ActionDescriptor则会将其包装在HttpActionDescriptorTracer类型中

要解决此问题,我们需要检查实现是否ActionDescriptor实现了IDecorator<HttpActionDescriptor>接口:

public override void OnActionExecuting(HttpActionContext actionContext)
{
  ...
  ReflectedHttpActionDescriptor reflectedActionDescriptor;

  // Check whether the ActionDescriptor is wrapped in a decorator or not.
  var wrapper = actionContext.ActionDescriptor as IDecorator<HttpActionDescriptor>;
  if (wrapper != null)
  {
    reflectedActionDescriptor = wrapper.Inner as ReflectedHttpActionDescriptor;
  }
  else
  {
    reflectedActionDescriptor = actionContext.ActionDescriptor as ReflectedHttpActionDescriptor;
  }

  if (reflectedActionDescriptor != null)
  {
    // get the custom attributes applied to the action return value
    var attrs = reflectedActionDescriptor
                  .MethodInfo
                  .ReturnTypeCustomAttributes
                  .GetCustomAttributes(typeof (SafeAttribute), false)
                  .OfType<SafeAttribute>()
                  .ToArray();
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)