Action/ActionResult/ExceptionFilterAttribute(s)

AllowAnonymousAttribute
Name cleanup in ReflectionActionDescriptorProvider
This commit is contained in:
Yishai Galatzer 2014-03-03 03:04:40 -08:00
parent 457016a6da
commit 4bb66937e3
6 changed files with 79 additions and 17 deletions

View File

@ -19,5 +19,7 @@ namespace Microsoft.AspNet.Mvc
public List<ParameterDescriptor> Parameters { get; set; } public List<ParameterDescriptor> Parameters { get; set; }
public List<IFilter> Filters { get; set; } public List<IFilter> Filters { get; set; }
public bool AllowAnonymous { get; set; }
} }
} }

View File

@ -0,0 +1,13 @@
using System;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public abstract class ActionFilterAttribute : Attribute, IActionFilter, IFilter
{
public abstract Task Invoke(ActionFilterContext context, Func<ActionFilterContext, Task> next);
public int Order { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public abstract class ActionResultFilterAttribute : Attribute, IActionResultFilter, IFilter
{
public abstract Task Invoke(ActionResultFilterContext context, Func<ActionResultFilterContext, Task> next);
public int Order { get; set; }
}
}

View File

@ -0,0 +1,9 @@
using System;
namespace Microsoft.AspNet.Mvc
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public sealed class AllowAnonymousAttribute : Attribute
{
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public abstract class ExceptionFilterAttribute : Attribute, IExceptionFilter, IFilter
{
public abstract Task Invoke(ExceptionFilterContext context, Func<ExceptionFilterContext, Task> next);
public int Order { get; set; }
}
}

View File

@ -43,7 +43,10 @@ namespace Microsoft.AspNet.Mvc
foreach (var cd in controllerDescriptors) foreach (var cd in controllerDescriptors)
{ {
var controllerFilters = GetOrderedFilterAttributes(cd.ControllerTypeInfo); var controllerAttributes = cd.ControllerTypeInfo.GetCustomAttributes(inherit: true).ToArray();
var filtersFromController = GetOrderedFilterAttributes(controllerAttributes);
bool allowAnonymous = IsAnonymous(controllerAttributes);
foreach (var methodInfo in cd.ControllerTypeInfo.DeclaredMethods) foreach (var methodInfo in cd.ControllerTypeInfo.DeclaredMethods)
{ {
@ -56,15 +59,19 @@ namespace Microsoft.AspNet.Mvc
foreach (var actionInfo in actionInfos) foreach (var actionInfo in actionInfos)
{ {
yield return BuildDescriptor(cd, methodInfo, actionInfo, controllerFilters); yield return BuildDescriptor(cd, methodInfo, actionInfo, filtersFromController, allowAnonymous);
} }
} }
} }
} }
private IFilter[] GetOrderedFilterAttributes(MemberInfo memberInfo) private bool IsAnonymous(object[] attributes)
{
return attributes.OfType<AllowAnonymousAttribute>().Any();
}
private IFilter[] GetOrderedFilterAttributes(object[] attributes)
{ {
var attributes = memberInfo.GetCustomAttributes(inherit: true);
var filters = attributes.OfType<IFilter>().OrderByDescending(filter => filter.Order); var filters = attributes.OfType<IFilter>().OrderByDescending(filter => filter.Order);
return filters.ToArray(); return filters.ToArray();
@ -73,7 +80,8 @@ namespace Microsoft.AspNet.Mvc
private ReflectedActionDescriptor BuildDescriptor(ControllerDescriptor controllerDescriptor, private ReflectedActionDescriptor BuildDescriptor(ControllerDescriptor controllerDescriptor,
MethodInfo methodInfo, MethodInfo methodInfo,
ActionInfo actionInfo, ActionInfo actionInfo,
IFilter[] controllerFilters) IFilter[] controllerFilters,
bool allowAnonymous)
{ {
var ad = new ReflectedActionDescriptor var ad = new ReflectedActionDescriptor
{ {
@ -107,37 +115,41 @@ namespace Microsoft.AspNet.Mvc
ad.Parameters = methodInfo.GetParameters().Select(p => _parameterDescriptorFactory.GetDescriptor(p)).ToList(); ad.Parameters = methodInfo.GetParameters().Select(p => _parameterDescriptorFactory.GetDescriptor(p)).ToList();
// TODO: add ordering support such that action filters are ahead of controller filters if they have the same order var attributes = methodInfo.GetCustomAttributes(inherit: true).ToArray();
var actionFilters = GetOrderedFilterAttributes(methodInfo);
ad.Filters = MergeSorted(actionFilters, controllerFilters); // TODO: add ordering support such that action filters are ahead of controller filters if they have the same order
var filtersFromAction = GetOrderedFilterAttributes(attributes);
ad.Filters = MergeSorted(filtersFromAction, controllerFilters);
ad.AllowAnonymous = allowAnonymous || IsAnonymous(attributes);
return ad; return ad;
} }
internal List<IFilter> MergeSorted(IFilter[] actionFilters, IFilter[] controllerFilters) private List<IFilter> MergeSorted(IFilter[] filtersFromAction, IFilter[] filtersFromController)
{ {
var list = new List<IFilter>(); var list = new List<IFilter>();
var count = actionFilters.Length + controllerFilters.Length; var count = filtersFromAction.Length + filtersFromController.Length;
for (int i = 0, j = 0; i + j < count; ) for (int i = 0, j = 0; i + j < count; )
{ {
if (i >= actionFilters.Length) if (i >= filtersFromAction.Length)
{ {
list.Add(controllerFilters[j++]); list.Add(filtersFromController[j++]);
} }
else if (j >= controllerFilters.Length) else if (j >= filtersFromController.Length)
{ {
list.Add(actionFilters[i++]); list.Add(filtersFromAction[i++]);
} }
else if (actionFilters[i].Order >= controllerFilters[j].Order) else if (filtersFromAction[i].Order >= filtersFromController[j].Order)
{ {
list.Add(actionFilters[i++]); list.Add(filtersFromAction[i++]);
} }
else else
{ {
list.Add(controllerFilters[j++]); list.Add(filtersFromController[j++]);
} }
} }