假设我有一个操作方法,如下所示:
[return: Safe]
public IEnumerable<string> Get([Safe] SomeData data)
{
return new string[] { "value1", "value2" };
}
[Safe]属性是我创建的自定义属性。我想创建一个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();
}
但是,如何检索放置在返回类型上的[Safe]属性呢?
采用这种方法可能会有一些值得探索的地方:
ModelMetadataProvider meta = actionContext.GetMetadataProvider();
但若这确实有效,那个么如何使它和ModelMetadataProvider
一起工作还不清楚。
有什么建议吗?
首先尝试将ActionDescriptor
属性从HttpActionContext
强制转换为ReflectedHttpActionDescriptor
。然后使用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();
}
...
}
更新:已启用跟踪
ActionDescriptor
的具体类型似乎取决于全局Web API服务是否包含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();
}
...
}