moving global filters to options
This commit is contained in:
parent
a468986155
commit
7ed2de297e
13
Mvc.sln
13
Mvc.sln
|
|
@ -74,6 +74,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AntiForgeryWebSite", "test\
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AddServicesWebSite", "test\WebSites\AddServicesWebSite\AddServicesWebSite.kproj", "{6A0B65CE-6B01-40D0-840D-EFF3680D1547}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "FiltersWebSite", "test\WebSites\FiltersWebSite\FiltersWebSite.kproj", "{1976AC4A-FEA4-4587-A158-D9F79736D2B6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -374,6 +376,16 @@ Global
|
|||
{6A0B65CE-6B01-40D0-840D-EFF3680D1547}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{6A0B65CE-6B01-40D0-840D-EFF3680D1547}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{6A0B65CE-6B01-40D0-840D-EFF3680D1547}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -409,5 +421,6 @@ Global
|
|||
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{A353B17E-A940-4CE8-8BF9-179E24A9041F} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{6A0B65CE-6B01-40D0-840D-EFF3680D1547} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<DevelopmentServerPort>51929</DevelopmentServerPort>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
|
||||
<DevelopmentServerPort>57394</DevelopmentServerPort>
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ using Microsoft.AspNet.Mvc;
|
|||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.ConfigurationModel;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using MvcSample.Web.Filters;
|
||||
using MvcSample.Web.Services;
|
||||
|
||||
#if ASPNET50
|
||||
using Autofac;
|
||||
using Microsoft.Framework.DependencyInjection.Autofac;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
#endif
|
||||
|
||||
namespace MvcSample.Web
|
||||
|
|
@ -42,6 +42,10 @@ namespace MvcSample.Web
|
|||
// sample's assemblies are loaded. This prevents loading controllers from other assemblies
|
||||
// when the sample is used in the Functional Tests.
|
||||
services.AddTransient<IControllerAssemblyProvider, TestAssemblyProvider<Startup>>();
|
||||
services.SetupOptions<MvcOptions>(options =>
|
||||
{
|
||||
options.Filters.Add(typeof(PassThroughAttribute), order: 17);
|
||||
});
|
||||
|
||||
// Create the autofac container
|
||||
ContainerBuilder builder = new ContainerBuilder();
|
||||
|
|
@ -72,6 +76,11 @@ namespace MvcSample.Web
|
|||
// sample's assemblies are loaded. This prevents loading controllers from other assemblies
|
||||
// when the sample is used in the Functional Tests.
|
||||
services.AddTransient<IControllerAssemblyProvider, TestAssemblyProvider<Startup>>();
|
||||
|
||||
services.SetupOptions<MvcOptions>(options =>
|
||||
{
|
||||
options.Filters.Add(typeof(PassThroughAttribute), order: 17);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ using Microsoft.AspNet.Mvc.Rendering;
|
|||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class Controller : IActionFilter, IAsyncActionFilter
|
||||
public class Controller : IActionFilter, IAsyncActionFilter, IOrderedFilter
|
||||
{
|
||||
private DynamicViewData _viewBag;
|
||||
|
||||
|
|
@ -80,6 +80,15 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
}
|
||||
|
||||
int IOrderedFilter.Order
|
||||
{
|
||||
get
|
||||
{
|
||||
// Controller-filter methods run closest the action by default.
|
||||
return int.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ViewResult"/> object that renders a view to the response.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -10,12 +10,9 @@ namespace Microsoft.AspNet.Mvc.Filters
|
|||
{
|
||||
public class DefaultFilterProvider : INestedProvider<FilterProviderContext>
|
||||
{
|
||||
private readonly ITypeActivator _typeActivator;
|
||||
|
||||
public DefaultFilterProvider(IServiceProvider serviceProvider, ITypeActivator typeActivator)
|
||||
public DefaultFilterProvider(IServiceProvider serviceProvider)
|
||||
{
|
||||
ServiceProvider = serviceProvider;
|
||||
_typeActivator = typeActivator;
|
||||
}
|
||||
|
||||
public int Order
|
||||
|
|
@ -78,15 +75,6 @@ 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.
|
||||
var 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// An implementation of <see cref="IGlobalFilterProvider"/> based on <see cref="MvcOptions"/>.
|
||||
/// </summary>
|
||||
public class DefaultGlobalFilterProvider : IGlobalFilterProvider
|
||||
{
|
||||
private readonly IReadOnlyList<IFilter> _filters;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="DefaultGlobalFilterProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="optionsAccessor">The options accessor for <see cref="MvcOptions"/>.</param>
|
||||
public DefaultGlobalFilterProvider(IOptionsAccessor<MvcOptions> optionsAccessor)
|
||||
{
|
||||
var filters = optionsAccessor.Options.Filters;
|
||||
_filters = filters.ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<IFilter> Filters
|
||||
{
|
||||
get
|
||||
{
|
||||
return _filters;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for adding filters to the global filters collection.
|
||||
/// </summary>
|
||||
public static class FilterCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a type representing an <see cref="IFilter"/> to a filter collection.
|
||||
/// </summary>
|
||||
/// <param name="filters">A collection of <see cref="IFilter"/>.</param>
|
||||
/// <param name="filterType">Type representing an <see cref="IFilter"/>.</param>
|
||||
/// <returns>An <see cref="IFilter"/> representing the added type.</returns>
|
||||
/// <remarks>
|
||||
/// Filter instances will be created using <see cref="Microsoft.Framework.DependencyInjection.ITypeActivator"/>.
|
||||
/// Use <see cref="AddService(ICollection{IFilter}, Type)"/> to register a service as a filter.
|
||||
/// </remarks>
|
||||
public static IFilter Add(
|
||||
[NotNull] this ICollection<IFilter> filters,
|
||||
[NotNull] Type filterType)
|
||||
{
|
||||
return Add(filters, filterType, order: 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a type representing an <see cref="IFilter"/> to a filter collection.
|
||||
/// </summary>
|
||||
/// <param name="filters">A collection of <see cref="IFilter"/>.</param>
|
||||
/// <param name="filterType">Type representing an <see cref="IFilter"/>.</param>
|
||||
/// <param name="order">The order of the added filter.</param>
|
||||
/// <returns>An <see cref="IFilter"/> representing the added type.</returns>
|
||||
/// <remarks>
|
||||
/// Filter instances will be created using <see cref="Microsoft.Framework.DependencyInjection.ITypeActivator"/>.
|
||||
/// Use <see cref="AddService(ICollection{IFilter}, Type)"/> to register a service as a filter.
|
||||
/// </remarks>
|
||||
public static IFilter Add(
|
||||
[NotNull] this ICollection<IFilter> filters,
|
||||
[NotNull] Type filterType,
|
||||
int order)
|
||||
{
|
||||
if (!typeof(IFilter).IsAssignableFrom(filterType))
|
||||
{
|
||||
var message = Resources.FormatTypeMustDeriveFromType(filterType.FullName, typeof(IFilter).FullName);
|
||||
throw new ArgumentException(message, nameof(filterType));
|
||||
}
|
||||
|
||||
var filter = new TypeFilterAttribute(filterType) { Order = order };
|
||||
filters.Add(filter);
|
||||
return filter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a type representing an <see cref="IFilter"/> to a filter collection.
|
||||
/// </summary>
|
||||
/// <param name="filters">A collection of <see cref="IFilter"/>.</param>
|
||||
/// <param name="filterType">Type representing an <see cref="IFilter"/>.</param>
|
||||
/// <returns>An <see cref="IFilter"/> representing the added service type.</returns>
|
||||
/// <remarks>
|
||||
/// Filter instances will created through dependency injection. Use
|
||||
/// <see cref="AddService(ICollection{IFilter}, Type)"/> to register a service that will be created via
|
||||
/// type activation.
|
||||
/// </remarks>
|
||||
public static IFilter AddService(
|
||||
[NotNull] this ICollection<IFilter> filters,
|
||||
[NotNull] Type filterType)
|
||||
{
|
||||
return AddService(filters, filterType, order: 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a type representing an <see cref="IFilter"/> to a filter collection.
|
||||
/// </summary>
|
||||
/// <param name="filters">A collection of <see cref="IFilter"/>.</param>
|
||||
/// <param name="filterType">Type representing an <see cref="IFilter"/>.</param>
|
||||
/// <param name="order">The order of the added filter.</param>
|
||||
/// <returns>An <see cref="IFilter"/> representing the added service type.</returns>
|
||||
/// <remarks>
|
||||
/// Filter instances will created through dependency injection. Use
|
||||
/// <see cref="AddService(ICollection{IFilter}, Type)"/> to register a service that will be created via
|
||||
/// type activation.
|
||||
/// </remarks>
|
||||
public static IFilter AddService(
|
||||
[NotNull] this ICollection<IFilter> filters,
|
||||
[NotNull] Type filterType,
|
||||
int order)
|
||||
{
|
||||
if (!typeof(IFilter).IsAssignableFrom(filterType))
|
||||
{
|
||||
var message = Resources.FormatTypeMustDeriveFromType(filterType.FullName, typeof(IFilter).FullName);
|
||||
throw new ArgumentException(message, nameof(filterType));
|
||||
}
|
||||
|
||||
var filter = new ServiceFilterAttribute(filterType) { Order = order };
|
||||
filters.Add(filter);
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,8 +3,34 @@
|
|||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// Descriptor for an <see cref="IFilter"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="FilterDescriptor"/> describes an <see cref="IFilter"/> with an order and scope.
|
||||
///
|
||||
/// Order and scope control the execution order of filters. Filters with a higher value of Order execute
|
||||
/// later in the pipeline.
|
||||
///
|
||||
/// When filters have the same Order, the Scope value is used to determine the order of execution. Filters
|
||||
/// with a higher value of Scope execute later in the pipeline. See <see cref="FilterScope"/> for commonly
|
||||
/// used scopes.
|
||||
///
|
||||
/// For <see cref="IExceptionFilter"/> implementions, the filter runs only after an exception has occurred,
|
||||
/// and so the observed order of execution will be opposite that of other filters.
|
||||
/// </remarks>
|
||||
public class FilterDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="FilterDescriptor"/>.
|
||||
/// </summary>
|
||||
/// <param name="filter">The <see cref="IFilter"/>.</param>
|
||||
/// <param name="filterScope">The filter scope.</param>
|
||||
/// <remarks>
|
||||
/// If the <paramref name="filter"/> implements <see cref="IOrderedFilter"/>, then the value of
|
||||
/// <see cref="Order"/> will be taken from <see cref="IOrderedFilter.Order"/>. Otherwise the value
|
||||
/// of <see cref="Order"/> will default to <c>0</c>.
|
||||
/// </remarks>
|
||||
public FilterDescriptor([NotNull] IFilter filter, int filterScope)
|
||||
{
|
||||
Filter = filter;
|
||||
|
|
@ -18,10 +44,19 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IFilter"/> instance.
|
||||
/// </summary>
|
||||
public IFilter Filter { get; private set; }
|
||||
|
||||
public int Order { get; private set; }
|
||||
/// <summary>
|
||||
/// The filter order.
|
||||
/// </summary>
|
||||
public int Order { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The filter scope.
|
||||
/// </summary>
|
||||
public int Scope { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to the collection of <see cref="IFilter"/> for globally registered filters.
|
||||
/// </summary>
|
||||
public interface IGlobalFilterProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the collection of <see cref="IFilter"/>.
|
||||
/// </summary>
|
||||
IReadOnlyList<IFilter> Filters { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.OptionDescriptors;
|
||||
using Microsoft.AspNet.Mvc.ReflectedModelBuilder;
|
||||
|
|
@ -25,6 +26,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
ValueProviderFactories = new List<ValueProviderFactoryDescriptor>();
|
||||
OutputFormatters = new List<OutputFormatterDescriptor>();
|
||||
InputFormatters = new List<InputFormatterDescriptor>();
|
||||
Filters = new List<IFilter>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -51,13 +53,19 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of the <see cref="OutputFormatterDescriptor" /> which are used to construct
|
||||
/// Gets a list of <see cref="IFilter"/> which are used to construct filters that
|
||||
/// apply to all actions.
|
||||
/// </summary>
|
||||
public ICollection<IFilter> Filters { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of the <see cref="OutputFormatterDescriptor" /> which are used to construct
|
||||
/// a list of <see cref="IOutputFormatter"/> by <see cref="IOutputFormattersProvider"/>.
|
||||
/// </summary>
|
||||
public List<OutputFormatterDescriptor> OutputFormatters { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of the <see cref="InputFormatterDescriptor" /> which are used to construct
|
||||
/// Gets a list of the <see cref="InputFormatterDescriptor" /> which are used to construct
|
||||
/// a list of <see cref="IInputFormatter"/> by <see cref="IInputFormattersProvider"/>.
|
||||
/// </summary>
|
||||
public List<InputFormatterDescriptor> InputFormatters { get; private set; }
|
||||
|
|
@ -86,13 +94,13 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of the <see cref="ModelBinderDescriptor" /> used by the
|
||||
/// Gets a list of the <see cref="ModelBinderDescriptor" /> used by the
|
||||
/// <see cref="ModelBinding.CompositeModelBinder" />.
|
||||
/// </summary>
|
||||
public List<ModelBinderDescriptor> ModelBinders { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of the <see cref="ModelValidatorProviderDescriptor" />s used by
|
||||
/// Gets a list of the <see cref="ModelValidatorProviderDescriptor" />s used by
|
||||
/// <see cref="ModelBinding.CompositeModelValidatorProvider"/>.
|
||||
/// </summary>
|
||||
public List<ModelValidatorProviderDescriptor> ModelValidatorProviders { get; } =
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.Filters;
|
||||
using Microsoft.AspNet.Mvc.ReflectedModelBuilder;
|
||||
using Microsoft.AspNet.Mvc.Routing;
|
||||
using Microsoft.AspNet.Routing;
|
||||
|
|
@ -27,19 +28,19 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
private readonly IControllerAssemblyProvider _controllerAssemblyProvider;
|
||||
private readonly IActionDiscoveryConventions _conventions;
|
||||
private readonly IEnumerable<IFilter> _globalFilters;
|
||||
private readonly IReadOnlyList<IFilter> _globalFilters;
|
||||
private readonly IEnumerable<IReflectedApplicationModelConvention> _modelConventions;
|
||||
private readonly IInlineConstraintResolver _constraintResolver;
|
||||
|
||||
public ReflectedActionDescriptorProvider(IControllerAssemblyProvider controllerAssemblyProvider,
|
||||
IActionDiscoveryConventions conventions,
|
||||
IEnumerable<IFilter> globalFilters,
|
||||
IGlobalFilterProvider globalFilters,
|
||||
IOptionsAccessor<MvcOptions> optionsAccessor,
|
||||
IInlineConstraintResolver constraintResolver)
|
||||
{
|
||||
_controllerAssemblyProvider = controllerAssemblyProvider;
|
||||
_conventions = conventions;
|
||||
_globalFilters = globalFilters ?? Enumerable.Empty<IFilter>();
|
||||
_globalFilters = globalFilters.Filters;
|
||||
_modelConventions = optionsAccessor.Options.ApplicationModelConventions;
|
||||
_constraintResolver = constraintResolver;
|
||||
}
|
||||
|
|
@ -352,8 +353,8 @@ namespace Microsoft.AspNet.Mvc
|
|||
IEnumerable<IFilter> controllerFilters,
|
||||
IEnumerable<IFilter> globalFilters)
|
||||
{
|
||||
actionDescriptor.FilterDescriptors = actionFilters
|
||||
.Select(f => new FilterDescriptor(f, FilterScope.Action))
|
||||
actionDescriptor.FilterDescriptors =
|
||||
actionFilters.Select(f => new FilterDescriptor(f, FilterScope.Action))
|
||||
.Concat(controllerFilters.Select(f => new FilterDescriptor(f, FilterScope.Controller)))
|
||||
.Concat(globalFilters.Select(f => new FilterDescriptor(f, FilterScope.Global)))
|
||||
.OrderBy(d => d, FilterDescriptorOrderComparer.Comparer)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,16 @@ namespace Microsoft.AspNet.Mvc.ReflectedModelBuilder
|
|||
// is needed to so that the result of ToList() is List<object>
|
||||
Attributes = actionMethod.GetCustomAttributes(inherit: true).OfType<object>().ToList();
|
||||
|
||||
Filters = Attributes.OfType<IFilter>().ToList();
|
||||
Filters = Attributes
|
||||
.OfType<IFilter>()
|
||||
.ToList();
|
||||
|
||||
var routeTemplateAttribute = Attributes.OfType<IRouteTemplateProvider>().FirstOrDefault();
|
||||
if (routeTemplateAttribute != null)
|
||||
{
|
||||
AttributeRouteModel = new ReflectedAttributeRouteModel(routeTemplateAttribute);
|
||||
}
|
||||
|
||||
HttpMethods = new List<string>();
|
||||
Parameters = new List<ReflectedParameterModel>();
|
||||
}
|
||||
|
|
@ -39,4 +48,4 @@ namespace Microsoft.AspNet.Mvc.ReflectedModelBuilder
|
|||
|
||||
public ReflectedAttributeRouteModel AttributeRouteModel { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,10 @@ namespace Microsoft.AspNet.Mvc.ReflectedModelBuilder
|
|||
// is needed to so that the result of ToList() is List<object>
|
||||
Attributes = ControllerType.GetCustomAttributes(inherit: true).OfType<object>().ToList();
|
||||
|
||||
Filters = Attributes.OfType<IFilter>().ToList();
|
||||
Filters = Attributes
|
||||
.OfType<IFilter>()
|
||||
.ToList();
|
||||
|
||||
RouteConstraints = Attributes.OfType<RouteConstraintAttribute>().ToList();
|
||||
|
||||
AttributeRoutes = Attributes.OfType<IRouteTemplateProvider>()
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
/// </summary>
|
||||
IReadOnlyList<IViewEngine> ViewEngines { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,10 @@ namespace Microsoft.AspNet.Mvc
|
|||
yield return describe.Instance<JsonOutputFormatter>(
|
||||
new JsonOutputFormatter(JsonOutputFormatter.CreateDefaultSettings(), indent: false));
|
||||
|
||||
// The IGlobalFilterProvider is used to build the action descriptors (likely once) and so should
|
||||
// remain transient to avoid keeping it in memory.
|
||||
yield return describe.Transient<IGlobalFilterProvider, DefaultGlobalFilterProvider>();
|
||||
|
||||
yield return describe.Transient<INestedProvider<FilterProviderContext>, DefaultFilterProvider>();
|
||||
|
||||
yield return describe.Transient<IModelValidatorProviderProvider, DefaultModelValidatorProviderProvider>();
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
return new ReflectedActionDescriptorProvider(
|
||||
controllerAssemblyProvider,
|
||||
actionDiscoveryConventions,
|
||||
null,
|
||||
new TestGlobalFilterProvider(),
|
||||
new MockMvcOptionsAccessor(),
|
||||
Mock.Of<IInlineConstraintResolver>());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
return new ReflectedActionDescriptorProvider(
|
||||
controllerAssemblyProvider.Object,
|
||||
actionDiscoveryConventions,
|
||||
null,
|
||||
new TestGlobalFilterProvider(),
|
||||
new MockMvcOptionsAccessor(),
|
||||
Mock.Of<IInlineConstraintResolver>());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,224 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Design;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.PipelineCore;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Xunit;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Filters
|
||||
{
|
||||
public class DefaultFilterProviderTest
|
||||
{
|
||||
[Fact]
|
||||
public void DefaultFilterProvider_UsesFilter_WhenItsNotIFilterFactory()
|
||||
{
|
||||
// Arrange
|
||||
var filter = Mock.Of<IFilter>();
|
||||
|
||||
var context = CreateFilterContext(new List<FilterItem>()
|
||||
{
|
||||
new FilterItem(new FilterDescriptor(filter, FilterScope.Global)),
|
||||
});
|
||||
|
||||
var provider = CreateProvider();
|
||||
|
||||
//System.Diagnostics.Debugger.Launch();
|
||||
//System.Diagnostics.Debugger.Break();
|
||||
// Act
|
||||
provider.Invoke(context, () => { });
|
||||
var results = context.Results;
|
||||
|
||||
// Assert
|
||||
var item = Assert.Single(results);
|
||||
Assert.Same(filter, item.Filter);
|
||||
Assert.Same(filter, item.Descriptor.Filter);
|
||||
Assert.Equal(0, item.Descriptor.Order);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultFilterProvider_UsesFilterFactory()
|
||||
{
|
||||
// Arrange
|
||||
var filter = Mock.Of<IFilter>();
|
||||
|
||||
var filterFactory = new Mock<IFilterFactory>();
|
||||
filterFactory
|
||||
.Setup(ff => ff.CreateInstance(It.IsAny<IServiceProvider>()))
|
||||
.Returns(filter);
|
||||
|
||||
var context = CreateFilterContext(new List<FilterItem>()
|
||||
{
|
||||
new FilterItem(new FilterDescriptor(filterFactory.Object, FilterScope.Global)),
|
||||
});
|
||||
|
||||
var provider = CreateProvider();
|
||||
|
||||
// Act
|
||||
provider.Invoke(context, () => { });
|
||||
var results = context.Results;
|
||||
|
||||
// Assert
|
||||
var item = Assert.Single(results);
|
||||
Assert.Same(filter, item.Filter);
|
||||
Assert.Same(filterFactory.Object, item.Descriptor.Filter);
|
||||
Assert.Equal(0, item.Descriptor.Order);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultFilterProvider_UsesFilterFactory_WithOrder()
|
||||
{
|
||||
// Arrange
|
||||
var filter = Mock.Of<IFilter>();
|
||||
|
||||
var filterFactory = new Mock<IFilterFactory>();
|
||||
filterFactory
|
||||
.Setup(ff => ff.CreateInstance(It.IsAny<IServiceProvider>()))
|
||||
.Returns(filter);
|
||||
|
||||
filterFactory.As<IOrderedFilter>().SetupGet(ff => ff.Order).Returns(17);
|
||||
|
||||
var context = CreateFilterContext(new List<FilterItem>()
|
||||
{
|
||||
new FilterItem(new FilterDescriptor(filterFactory.Object, FilterScope.Global)),
|
||||
});
|
||||
|
||||
var provider = CreateProvider();
|
||||
|
||||
// Act
|
||||
provider.Invoke(context, () => { });
|
||||
var results = context.Results;
|
||||
|
||||
// Assert
|
||||
var item = Assert.Single(results);
|
||||
Assert.Same(filter, item.Filter);
|
||||
Assert.Same(filterFactory.Object, item.Descriptor.Filter);
|
||||
Assert.Equal(17, item.Descriptor.Order);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultFilterProvider_UsesFilterFactory_WithIFilterContainer()
|
||||
{
|
||||
// Arrange
|
||||
var filter = new Mock<IFilterContainer>();
|
||||
filter.SetupAllProperties();
|
||||
|
||||
var filterFactory = new Mock<IFilterFactory>();
|
||||
filterFactory
|
||||
.Setup(ff => ff.CreateInstance(It.IsAny<IServiceProvider>()))
|
||||
.Returns(filter.As<IFilter>().Object);
|
||||
|
||||
var context = CreateFilterContext(new List<FilterItem>()
|
||||
{
|
||||
new FilterItem(new FilterDescriptor(filterFactory.Object, FilterScope.Global)),
|
||||
});
|
||||
|
||||
var provider = CreateProvider();
|
||||
|
||||
// Act
|
||||
provider.Invoke(context, () => { });
|
||||
var results = context.Results;
|
||||
|
||||
// Assert
|
||||
var item = Assert.Single(results);
|
||||
Assert.Same(filter.Object, item.Filter);
|
||||
Assert.Same(filterFactory.Object, ((IFilterContainer)item.Filter).FilterDefinition);
|
||||
Assert.Same(filterFactory.Object, item.Descriptor.Filter);
|
||||
Assert.Equal(0, item.Descriptor.Order);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultFilterProvider_InsertsController_DefaultOrder()
|
||||
{
|
||||
// Arrange
|
||||
var filter1 = new Mock<IOrderedFilter>();
|
||||
filter1.SetupGet(f => f.Order).Returns(int.MaxValue);
|
||||
|
||||
var filter2 = new Mock<IOrderedFilter>();
|
||||
filter2.SetupGet(f => f.Order).Returns(int.MaxValue);
|
||||
|
||||
var context = CreateFilterContext(new List<FilterItem>()
|
||||
{
|
||||
new FilterItem(new FilterDescriptor(filter1.Object, FilterScope.Global)),
|
||||
new FilterItem(new FilterDescriptor(filter2.Object, FilterScope.Action)),
|
||||
});
|
||||
|
||||
var controller = new Controller();
|
||||
context.ActionContext.Controller = controller;
|
||||
|
||||
var provider = CreateProvider();
|
||||
|
||||
// Act
|
||||
provider.Invoke(context, () => { });
|
||||
var results = context.Results;
|
||||
|
||||
// Assert
|
||||
var controllerItem = results[1];
|
||||
Assert.Same(controller, controllerItem.Filter);
|
||||
Assert.Same(controller, controllerItem.Descriptor.Filter);
|
||||
Assert.Equal(FilterScope.Controller, controllerItem.Descriptor.Scope);
|
||||
Assert.Equal(Int32.MaxValue, controllerItem.Descriptor.Order);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultFilterProvider_InsertsController_CustomOrder()
|
||||
{
|
||||
// Arrange
|
||||
var filter1 = new Mock<IOrderedFilter>();
|
||||
filter1.SetupGet(f => f.Order).Returns(0);
|
||||
|
||||
var filter2 = new Mock<IOrderedFilter>();
|
||||
filter2.SetupGet(f => f.Order).Returns(int.MaxValue);
|
||||
|
||||
var context = CreateFilterContext(new List<FilterItem>()
|
||||
{
|
||||
new FilterItem(new FilterDescriptor(filter1.Object, FilterScope.Global)),
|
||||
new FilterItem(new FilterDescriptor(filter2.Object, FilterScope.Action)),
|
||||
});
|
||||
|
||||
var controller = new Mock<IOrderedFilter>();
|
||||
controller.SetupGet(f => f.Order).Returns(17);
|
||||
|
||||
context.ActionContext.Controller = controller.Object;
|
||||
|
||||
var provider = CreateProvider();
|
||||
|
||||
// Act
|
||||
provider.Invoke(context, () => { });
|
||||
var results = context.Results;
|
||||
|
||||
// Assert
|
||||
var controllerItem = results[1];
|
||||
Assert.Same(controller.Object, controllerItem.Filter);
|
||||
Assert.Same(controller.Object, controllerItem.Descriptor.Filter);
|
||||
Assert.Equal(FilterScope.Controller, controllerItem.Descriptor.Scope);
|
||||
Assert.Equal(17, controllerItem.Descriptor.Order);
|
||||
}
|
||||
|
||||
private DefaultFilterProvider CreateProvider()
|
||||
{
|
||||
var services = new ServiceContainer();
|
||||
|
||||
return new DefaultFilterProvider(services);
|
||||
}
|
||||
|
||||
private FilterProviderContext CreateFilterContext(List<FilterItem> items)
|
||||
{
|
||||
var actionContext = CreateActionContext();
|
||||
actionContext.ActionDescriptor.FilterDescriptors = new List<FilterDescriptor>(
|
||||
items.Select(item => item.Descriptor));
|
||||
|
||||
return new FilterProviderContext(actionContext, items);
|
||||
}
|
||||
|
||||
private ActionContext CreateActionContext()
|
||||
{
|
||||
return new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class FilterCollectionExtensionsTest
|
||||
{
|
||||
[Fact]
|
||||
public void Add_UsesTypeFilterAttribute()
|
||||
{
|
||||
// Arrange
|
||||
var collection = new Collection<IFilter>();
|
||||
|
||||
// Act
|
||||
var added = collection.Add(typeof(MyFilter));
|
||||
|
||||
// Assert
|
||||
var typeFilter = Assert.IsType<TypeFilterAttribute>(added);
|
||||
Assert.Equal(typeof(MyFilter), typeFilter.ImplementationType);
|
||||
Assert.Same(typeFilter, Assert.Single(collection));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Add_WithOrder_SetsOrder()
|
||||
{
|
||||
// Arrange
|
||||
var collection = new Collection<IFilter>();
|
||||
|
||||
// Act
|
||||
var added = collection.Add(typeof(MyFilter), 17);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(17, Assert.IsAssignableFrom<IOrderedFilter>(added).Order);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Add_ThrowsOnNonIFilter()
|
||||
{
|
||||
// Arrange
|
||||
var collection = new Collection<IFilter>();
|
||||
|
||||
var expectedMessage =
|
||||
"The type 'Microsoft.AspNet.Mvc.FilterCollectionExtensionsTest+NonFilter' must derive from " +
|
||||
"'Microsoft.AspNet.Mvc.IFilter'." + Environment.NewLine +
|
||||
"Parameter name: filterType";
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<ArgumentException>(() => { collection.Add(typeof(NonFilter)); });
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedMessage, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddService_UsesServiceFilterAttribute()
|
||||
{
|
||||
// Arrange
|
||||
var collection = new Collection<IFilter>();
|
||||
|
||||
// Act
|
||||
var added = collection.AddService(typeof(MyFilter));
|
||||
|
||||
// Assert
|
||||
var serviceFilter = Assert.IsType<ServiceFilterAttribute>(added);
|
||||
Assert.Equal(typeof(MyFilter), serviceFilter.ServiceType);
|
||||
Assert.Same(serviceFilter, Assert.Single(collection));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddService_SetsOrder()
|
||||
{
|
||||
// Arrange
|
||||
var collection = new Collection<IFilter>();
|
||||
|
||||
// Act
|
||||
var added = collection.AddService(typeof(MyFilter), 17);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(17, Assert.IsAssignableFrom<IOrderedFilter>(added).Order);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddService_ThrowsOnNonIFilter()
|
||||
{
|
||||
// Arrange
|
||||
var collection = new Collection<IFilter>();
|
||||
|
||||
var expectedMessage =
|
||||
"The type 'Microsoft.AspNet.Mvc.FilterCollectionExtensionsTest+NonFilter' must derive from " +
|
||||
"'Microsoft.AspNet.Mvc.IFilter'." + Environment.NewLine +
|
||||
"Parameter name: filterType";
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<ArgumentException>(() => { collection.AddService(typeof(NonFilter)); });
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedMessage, ex.Message);
|
||||
}
|
||||
|
||||
private class MyFilter : IFilter, IOrderedFilter
|
||||
{
|
||||
public int Order
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
private class NonFilter
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ using Microsoft.AspNet.Routing;
|
|||
using Microsoft.AspNet.Mvc.Routing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using Microsoft.AspNet.Mvc.Filters;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Test
|
||||
{
|
||||
|
|
@ -1029,7 +1030,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
var provider = new ReflectedActionDescriptorProvider(
|
||||
assemblyProvider.Object,
|
||||
conventions,
|
||||
filters,
|
||||
new TestGlobalFilterProvider(filters),
|
||||
new MockMvcOptionsAccessor(),
|
||||
Mock.Of<IInlineConstraintResolver>());
|
||||
|
||||
|
|
@ -1049,7 +1050,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
var provider = new ReflectedActionDescriptorProvider(
|
||||
assemblyProvider.Object,
|
||||
conventions,
|
||||
Enumerable.Empty<IFilter>(),
|
||||
new TestGlobalFilterProvider(),
|
||||
new MockMvcOptionsAccessor(),
|
||||
Mock.Of<IInlineConstraintResolver>());
|
||||
|
||||
|
|
@ -1068,7 +1069,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
var provider = new ReflectedActionDescriptorProvider(
|
||||
assemblyProvider.Object,
|
||||
conventions,
|
||||
null,
|
||||
new TestGlobalFilterProvider(),
|
||||
new MockMvcOptionsAccessor(),
|
||||
null);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.Filters;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class TestGlobalFilterProvider : IGlobalFilterProvider
|
||||
{
|
||||
public TestGlobalFilterProvider()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public TestGlobalFilterProvider(IEnumerable<IFilter> filters)
|
||||
{
|
||||
var filterList = new List<IFilter>();
|
||||
Filters = filterList;
|
||||
|
||||
if (filters != null)
|
||||
{
|
||||
filterList.AddRange(filters);
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<IFilter> Filters { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.TestHost;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||
{
|
||||
public class FiltersTest
|
||||
{
|
||||
private readonly IServiceProvider _services = TestHelper.CreateServices("FiltersWebSite");
|
||||
private readonly Action<IApplicationBuilder> _app = new FiltersWebSite.Startup().Configure;
|
||||
|
||||
[Fact]
|
||||
public async Task ListAllFilters()
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_services, _app);
|
||||
var client = server.CreateClient();
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("http://localhost/Products/GetPrice/5");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<decimal>(body);
|
||||
|
||||
Assert.Equal(19.95m, result);
|
||||
|
||||
var filters = response.Headers.GetValues("filters");
|
||||
Assert.Equal(
|
||||
new string[]
|
||||
{
|
||||
// This one uses order to set itself 'first' even though it appears on the controller
|
||||
"FiltersWebSite.PassThroughActionFilter",
|
||||
|
||||
// Configured as global with default order
|
||||
"FiltersWebSite.GlobalExceptionFilter",
|
||||
|
||||
// Configured on the controller with default order
|
||||
"FiltersWebSite.PassThroughResultFilter",
|
||||
|
||||
// Configured on the action with default order
|
||||
"FiltersWebSite.PassThroughActionFilter",
|
||||
|
||||
// The controller itself
|
||||
"FiltersWebSite.ProductsController",
|
||||
},
|
||||
filters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,8 @@
|
|||
"AntiForgeryWebSite": "",
|
||||
"BasicWebSite": "",
|
||||
"CompositeViewEngine": "",
|
||||
"ConnegWebsite": "",
|
||||
"ConnegWebsite": "",
|
||||
"FiltersWebSite": "",
|
||||
"FormatterWebSite": "",
|
||||
"InlineConstraintsWebSite": "",
|
||||
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using System.Linq;
|
||||
|
||||
namespace FiltersWebSite
|
||||
{
|
||||
// This controller will list the filters that are configured for each action in a header.
|
||||
// This exercises the merging of filters with the global filters collection.
|
||||
[PassThroughActionFilter(Order = -2)]
|
||||
[PassThroughResultFilter]
|
||||
public class ProductsController : Controller
|
||||
{
|
||||
[PassThroughActionFilter]
|
||||
public decimal GetPrice(int id)
|
||||
{
|
||||
return 19.95m;
|
||||
}
|
||||
|
||||
public override void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
// Log the filter names in a header
|
||||
context.HttpContext.Response.Headers.Add(
|
||||
"filters",
|
||||
context.Filters.Select(f => f.GetType().FullName).ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace FiltersWebSite
|
||||
{
|
||||
public class GlobalExceptionFilter : IExceptionFilter
|
||||
{
|
||||
public void OnException(ExceptionContext context)
|
||||
{
|
||||
context.Result = new ContentResult()
|
||||
{
|
||||
Content = "GlobalExceptionFilter.OnException",
|
||||
ContentType = "text/plain",
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace FiltersWebSite
|
||||
{
|
||||
public class PassThroughActionFilter : ActionFilterAttribute
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace FiltersWebSite
|
||||
{
|
||||
public class PassThroughResultFilter : ResultFilterAttribute
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">12.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>1976ac4a-fea4-4587-a158-d9f79736d2b6</ProjectGuid>
|
||||
<OutputType>Web</OutputType>
|
||||
<RootNamespace>FiltersWebSite</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(OutputType) == 'Console'">
|
||||
<DebuggerFlavor>ConsoleDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(OutputType) == 'Web'">
|
||||
<DebuggerFlavor>WebDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'" Label="Configuration">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<DevelopmentServerPort>25980</DevelopmentServerPort>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace FiltersWebSite
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
var configuration = app.GetTestConfiguration();
|
||||
|
||||
app.UseServices(services =>
|
||||
{
|
||||
services.AddMvc(configuration);
|
||||
|
||||
services.SetupOptions<MvcOptions>(options =>
|
||||
{
|
||||
options.Filters.Add(new GlobalExceptionFilter());
|
||||
});
|
||||
});
|
||||
|
||||
app.UseMvc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Mvc": "",
|
||||
"Microsoft.AspNet.Server.IIS": "1.0.0-*",
|
||||
"Microsoft.AspNet.Mvc.TestConfiguration": ""
|
||||
},
|
||||
"frameworks" : {
|
||||
"aspnet50": { },
|
||||
"aspnetcore50": { }
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue