Adding controller-as-filter support
If the controller implements IFilter, it will be added to the filters collection. It's hardcoded to be 'first' as it was in MVC, but can be overridden by implementing IOrderedFilter.
This commit is contained in:
parent
a9a7663cbd
commit
7a8dc36553
|
|
@ -41,14 +41,20 @@ namespace Microsoft.AspNet.Mvc.Filters
|
|||
|
||||
public virtual void Invoke(FilterProviderContext context, Action callNext)
|
||||
{
|
||||
if (context.ActionDescriptor.FilterDescriptors != null)
|
||||
if (context.ActionContext.ActionDescriptor.FilterDescriptors != null)
|
||||
{
|
||||
foreach (var item in context.Result)
|
||||
foreach (var item in context.Results)
|
||||
{
|
||||
ProvideFilter(context, item);
|
||||
}
|
||||
}
|
||||
|
||||
var controllerFilter = context.ActionContext.Controller as IFilter;
|
||||
if (controllerFilter != null)
|
||||
{
|
||||
InsertControllerAsFilter(context, controllerFilter);
|
||||
}
|
||||
|
||||
if (callNext != null)
|
||||
{
|
||||
callNext();
|
||||
|
|
@ -84,6 +90,37 @@ namespace Microsoft.AspNet.Mvc.Filters
|
|||
}
|
||||
}
|
||||
|
||||
private void InsertControllerAsFilter(FilterProviderContext context, IFilter controllerFilter)
|
||||
{
|
||||
// If the controller implements a filter, and doesn't specify order, then it should
|
||||
// run closest to the action.
|
||||
int order = Int32.MaxValue;
|
||||
var orderedControllerFilter = controllerFilter as IOrderedFilter;
|
||||
if (orderedControllerFilter == null)
|
||||
{
|
||||
order = orderedControllerFilter.Order;
|
||||
}
|
||||
|
||||
var descriptor = new FilterDescriptor(controllerFilter, FilterScope.Controller);
|
||||
var item = new FilterItem(descriptor, controllerFilter);
|
||||
|
||||
// BinarySearch will return the index of where the item _should_be_ in the list.
|
||||
//
|
||||
// If index > 0:
|
||||
// Other items in the list have the same order and scope - the item was 'found'.
|
||||
//
|
||||
// If index < 0:
|
||||
// No other items in the list have the same order and scope - the item was not 'found'
|
||||
// Index will be the bitwise compliment of of the 'right' location.
|
||||
var index = context.Results.BinarySearch(item, FilterItemOrderComparer.Comparer);
|
||||
if (index < 0)
|
||||
{
|
||||
index = ~index;
|
||||
}
|
||||
|
||||
context.Results.Insert(index, item);
|
||||
}
|
||||
|
||||
private void ApplyFilterToContainer(object actualFilter, IFilter filterMetadata)
|
||||
{
|
||||
Contract.Assert(actualFilter != null, "actualFilter should not be null");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All Rights Reserved
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
||||
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
||||
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class FilterItemOrderComparer : IComparer<FilterItem>
|
||||
{
|
||||
private static readonly FilterItemOrderComparer _comparer = new FilterItemOrderComparer();
|
||||
|
||||
public static FilterItemOrderComparer Comparer { get { return _comparer; } }
|
||||
|
||||
public int Compare([NotNull] FilterItem x, [NotNull] FilterItem y)
|
||||
{
|
||||
return FilterDescriptorOrderComparer.Comparer.Compare(x.Descriptor, y.Descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,16 +21,16 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
public class FilterProviderContext
|
||||
{
|
||||
public FilterProviderContext(ActionDescriptor actionDescriptor, List<FilterItem> items)
|
||||
public FilterProviderContext([NotNull] ActionContext actionContext, [NotNull] List<FilterItem> items)
|
||||
{
|
||||
ActionDescriptor = actionDescriptor;
|
||||
Result = items;
|
||||
ActionContext = actionContext;
|
||||
Results = items;
|
||||
}
|
||||
|
||||
// Input
|
||||
public ActionDescriptor ActionDescriptor { get; set; }
|
||||
public ActionContext ActionContext { get; set; }
|
||||
|
||||
// Result
|
||||
public List<FilterItem> Result { get; set; }
|
||||
// Results
|
||||
public List<FilterItem> Results { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@
|
|||
<Compile Include="DefaultControllerFactory.cs" />
|
||||
<Compile Include="DefaultParameterDescriptorFactory.cs" />
|
||||
<Compile Include="Extensions\IEnumerableExtensions.cs" />
|
||||
<Compile Include="Filters\FilterItemOrderComparer.cs" />
|
||||
<Compile Include="Filters\TypeFilterAttribute.cs" />
|
||||
<Compile Include="Filters\ActionExecutedContext.cs" />
|
||||
<Compile Include="Filters\ActionExecutingContext.cs" />
|
||||
|
|
|
|||
|
|
@ -74,11 +74,11 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
public async Task InvokeActionAsync()
|
||||
{
|
||||
_actionContext.Controller = _controllerFactory.CreateController(_actionContext);
|
||||
|
||||
_filters = GetFilters();
|
||||
_cursor = new FilterCursor(_filters);
|
||||
|
||||
_actionContext.Controller = _controllerFactory.CreateController(_actionContext);
|
||||
|
||||
// >> ExceptionFilters >> AuthorizationFilters >> ActionFilters >> Action
|
||||
await InvokeActionExceptionFilters();
|
||||
|
||||
|
|
@ -116,12 +116,12 @@ namespace Microsoft.AspNet.Mvc
|
|||
private IFilter[] GetFilters()
|
||||
{
|
||||
var filterProviderContext = new FilterProviderContext(
|
||||
_descriptor,
|
||||
_actionContext,
|
||||
_descriptor.FilterDescriptors.Select(fd => new FilterItem(fd)).ToList());
|
||||
|
||||
_filterProvider.Invoke(filterProviderContext);
|
||||
|
||||
return filterProviderContext.Result.Select(item => item.Filter).Where(filter => filter != null).ToArray();
|
||||
return filterProviderContext.Results.Select(item => item.Filter).Where(filter => filter != null).ToArray();
|
||||
}
|
||||
|
||||
private async Task InvokeActionExceptionFilters()
|
||||
|
|
|
|||
|
|
@ -1255,7 +1255,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
filterProvider
|
||||
.Setup(fp => fp.Invoke(It.IsAny<FilterProviderContext>()))
|
||||
.Callback<FilterProviderContext>(
|
||||
context => context.Result.AddRange(filters.Select(f => new FilterItem(null, f))));
|
||||
context => context.Results.AddRange(filters.Select(f => new FilterItem(null, f))));
|
||||
|
||||
var invoker = new ReflectedActionInvoker(
|
||||
actionContext,
|
||||
|
|
|
|||
Loading…
Reference in New Issue