Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

Adding IFilterFactory #345

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 19 additions & 10 deletions samples/MvcSample.Web/Filters/InspectResultPageAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Filters;
using MvcSample.Web.Models;

namespace MvcSample.Web.Filters
{
public class InspectResultPageAttribute : ActionFilterAttribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class InspectResultPageAttribute : Attribute, IFilterFactory
{
public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
public IFilter CreateInstance(IServiceProvider serviceProvider)
{
var viewResult = context.Result as ViewResult;
return new InspectResultPageFilter();
}

if (viewResult != null)
private class InspectResultPageFilter : IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
var user = viewResult.ViewData.Model as User;
var viewResult = context.Result as ViewResult;

if (user != null)
if (viewResult != null)
{
user.Name += "**" + user.Name + "**";
var user = viewResult.ViewData.Model as User;

if (user != null)
{
user.Name += "**" + user.Name + "**";
}
}
}

await next();
public void OnResultExecuted(ResultExecutedContext context)
{
}
}
}
}
10 changes: 7 additions & 3 deletions samples/MvcSample.Web/Filters/UserNameProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ namespace MvcSample.Web.Filters
{
public class UserNameProvider : IActionFilter
{
private static readonly string[] _userNames = new[] { "Jon", "David", "Goliath" };
private static int _index;
private readonly UserNameService _nameService;

public UserNameProvider(UserNameService nameService)
{
_nameService = nameService;
}

public void OnActionExecuting(ActionExecutingContext context)
{
Expand All @@ -17,7 +21,7 @@ public void OnActionExecuting(ActionExecutingContext context)

if (string.IsNullOrWhiteSpace(userName))
{
context.ActionArguments["userName"] = _userNames[(_index++)%3];
context.ActionArguments["userName"] = _nameService.GetName();
}
}

Expand Down
15 changes: 15 additions & 0 deletions samples/MvcSample.Web/Filters/UserNameService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Microsoft.AspNet.Mvc;

namespace MvcSample.Web.Filters
{
public class UserNameService
{
private static readonly string[] _userNames = new[] { "Jon", "David", "Goliath" };
private static int _index;

public string GetName()
{
return _userNames[_index++ % 3];
}
}
}
1 change: 1 addition & 0 deletions samples/MvcSample.Web/MvcSample.Web.kproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<Compile Include="Filters\InspectResultPageAttribute.cs" />
<Compile Include="Filters\PassThroughAttribute.cs" />
<Compile Include="Filters\UserNameProvider.cs" />
<Compile Include="Filters\UserNameService.cs" />
<Compile Include="Home2Controller.cs" />
<Compile Include="HomeController.cs" />
<Compile Include="LinkController.cs" />
Expand Down
2 changes: 2 additions & 0 deletions samples/MvcSample.Web/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Routing;
using MvcSample.Web.Filters;

namespace MvcSample.Web
{
Expand All @@ -13,6 +14,7 @@ public void Configuration(IBuilder app)
{
services.AddMvc();
services.AddSingleton<PassThroughAttribute, PassThroughAttribute>();
services.AddSingleton<UserNameService, UserNameService>();
});

app.UseMvc(routes =>
Expand Down
43 changes: 11 additions & 32 deletions src/Microsoft.AspNet.Mvc.Core/Filters/DefaultFilterProvider.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Diagnostics.Contracts;
using Microsoft.AspNet.DependencyInjection;
using Microsoft.AspNet.Mvc.Core;

namespace Microsoft.AspNet.Mvc.Filters
{
Expand Down Expand Up @@ -46,45 +47,23 @@ public virtual void ProvideFilter(FilterProviderContext context, FilterItem filt

var filter = filterItem.Descriptor.Filter;

var serviceFilterSignature = filter as IServiceFilter;
if (serviceFilterSignature != null)
var filterFactory = filter as IFilterFactory;
if (filterFactory == null)
{
var serviceFilter = ServiceProvider.GetService(serviceFilterSignature.ServiceType) as IFilter;

if (serviceFilter == null)
{
throw new InvalidOperationException("Service filter must be of type IFilter");
}

filterItem.Filter = serviceFilter;
filterItem.Filter = filter;
}
else
{
var typeFilterSignature = filter as ITypeFilter;
if (typeFilterSignature != null)
{
if (typeFilterSignature.ImplementationType == null)
{
throw new InvalidOperationException("Type filter must provide a type to instantiate");
}
filterItem.Filter = filterFactory.CreateInstance(ServiceProvider);

if (!typeof (IFilter).IsAssignableFrom(typeFilterSignature.ImplementationType))
{
throw new InvalidOperationException("Type filter must implement IFilter");
}

var typeFilter = (IFilter)_typeActivator.CreateInstance(
ServiceProvider,
typeFilterSignature.ImplementationType,
typeFilterSignature.Arguments);

ApplyFilterToContainer(typeFilter, filter);
filterItem.Filter = typeFilter;
}
else
if (filterItem.Filter == null)
{
filterItem.Filter = filter;
throw new InvalidOperationException(Resources.FormatTypeMethodMustReturnNotNullValue(
"CreateInstance",
typeof(IFilterFactory).Name));
}

ApplyFilterToContainer(filterItem.Filter, filterFactory);
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/Microsoft.AspNet.Mvc.Core/Filters/IFilterFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace Microsoft.AspNet.Mvc
{
public interface IFilterFactory : IFilter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe filter factory needs order, otherwise you can't apply it globally and get it ordered against other filters

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you need order you can just also implement IOrderedFilter. Our two implementations have both interfaces.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, will open a follow up by for global filters, will include details about the need to include ordering on IFilterFactory when that's implemented.

Edit: #349 filed

{
IFilter CreateInstance([NotNull] IServiceProvider serviceProvider);
}
}
9 changes: 0 additions & 9 deletions src/Microsoft.AspNet.Mvc.Core/Filters/IServiceFilter.cs

This file was deleted.

11 changes: 0 additions & 11 deletions src/Microsoft.AspNet.Mvc.Core/Filters/ITypeFilter.cs

This file was deleted.

20 changes: 18 additions & 2 deletions src/Microsoft.AspNet.Mvc.Core/Filters/ServiceFilterAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
using System;
using System.Diagnostics;
using Microsoft.AspNet.Mvc.Core;

namespace Microsoft.AspNet.Mvc
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
[DebuggerDisplay("ServiceFilter: Type={ServiceType} Order={Order}")]
public class ServiceFilterAttribute : Attribute, IServiceFilter
public class ServiceFilterAttribute : Attribute, IFilterFactory, IOrderedFilter
{
public ServiceFilterAttribute(Type type)
public ServiceFilterAttribute([NotNull] Type type)
{
ServiceType = type;
}

public Type ServiceType { get; private set; }

public int Order { get; set; }

public IFilter CreateInstance([NotNull] IServiceProvider serviceProvider)
{
var service = serviceProvider.GetService(ServiceType);

var filter = service as IFilter;
if (filter == null)
{
throw new InvalidOperationException(Resources.FormatFilterFactoryAttribute_TypeMustImplementIFilter(
typeof(ServiceFilterAttribute).Name,
typeof(IFilter).Name));
}

return filter;
}
}
}
22 changes: 20 additions & 2 deletions src/Microsoft.AspNet.Mvc.Core/Filters/TypeFilterAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
using System;
using System.Diagnostics;
using Microsoft.AspNet.DependencyInjection;
using Microsoft.AspNet.Mvc.Core;

namespace Microsoft.AspNet.Mvc
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
[DebuggerDisplay("TypeFilter: Type={ImplementationType} Order={Order}")]
public class TypeFilterAttribute : Attribute, ITypeFilter, IOrderedFilter
public class TypeFilterAttribute : Attribute, IFilterFactory, IOrderedFilter
{
public TypeFilterAttribute(Type type)
public TypeFilterAttribute([NotNull] Type type)
{
ImplementationType = type;
}
Expand All @@ -17,5 +19,21 @@ public TypeFilterAttribute(Type type)
public Type ImplementationType { get; private set; }

public int Order { get; set; }

public IFilter CreateInstance([NotNull] IServiceProvider serviceProvider)
{
var activator = serviceProvider.GetService<ITypeActivator>();
var obj = activator.CreateInstance(serviceProvider, ImplementationType, Arguments ?? new object[0]);

var filter = obj as IFilter;
if (filter == null)
{
throw new InvalidOperationException(Resources.FormatFilterFactoryAttribute_TypeMustImplementIFilter(
typeof(TypeFilterAttribute).Name,
typeof(IFilter).Name));
}

return filter;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@
<Compile Include="Filters\IFilterContainer.cs" />
<Compile Include="Filters\IOrderedFilter.cs" />
<Compile Include="Filters\IResultFilter.cs" />
<Compile Include="Filters\IServiceFilter.cs" />
<Compile Include="Filters\ITypeFilter.cs" />
<Compile Include="Filters\IFilterFactory.cs" />
<Compile Include="Filters\ResultExecutedContext.cs" />
<Compile Include="Filters\ResultExecutingContext.cs" />
<Compile Include="Filters\ResultExecutionDelegate.cs" />
Expand Down
Loading