Action filters & Authorization Filters working

This commit is contained in:
Yishai Galatzer 2014-03-05 20:42:21 -08:00
parent 6fed92695b
commit 772f833dc9
10 changed files with 102 additions and 43 deletions

View File

@ -0,0 +1,35 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
namespace MvcSample.Filters
{
public class AgeEnhancerAttribute : ActionFilterAttribute
{
public async override Task Invoke(ActionFilterContext context, Func<Task> next)
{
object age = null;
if (context.ActionParameters.TryGetValue("age", out age))
{
if (age is int)
{
var intAge = (int) age;
if (intAge < 21)
{
intAge += 5;
}
else if (intAge > 30)
{
intAge = 29;
}
context.ActionParameters["age"] = intAge;
}
}
await next();
}
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
namespace MvcSample
{
public class PassThroughAttribute : AuthorizationFilterAttribute
{
public async override Task Invoke(AuthorizationFilterContext context, Func<Task> next)
{
await next();
}
}
}

View File

@ -1,14 +1,13 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc;
using MvcSample.Filters;
using MvcSample.Models;
namespace MvcSample
{
// Expected order in descriptor - object -> int -> string
// TODO: Add a real filter here
[ServiceFilter(typeof(object), Order = 1)]
[ServiceFilter(typeof(string))]
[ServiceFilter(typeof(PassThroughAttribute), Order = 1)]
[ServiceFilter(typeof(PassThroughAttribute))]
[PassThrough(Order = 0)]
[PassThrough(Order = 2)]
public class FiltersController : Controller
@ -16,18 +15,13 @@ namespace MvcSample
private readonly User _user = new User() { Name = "User Name", Address = "Home Address" };
// TODO: Add a real filter here
[ServiceFilter(typeof(int))]
public IActionResult Index()
[ServiceFilter(typeof(PassThroughAttribute))]
[AgeEnhancer]
public IActionResult Index(int age)
{
_user.Age = age;
return View("MyView", _user);
}
}
public class PassThroughAttribute : AuthorizationFilterAttribute
{
public async override Task Invoke(AuthorizationFilterContext context, Func<Task> next)
{
await next();
}
}
}
}

View File

@ -4,5 +4,6 @@
{
public string Name { get; set; }
public string Address { get; set; }
public int Age { get; set; }
}
}

View File

@ -36,6 +36,8 @@ namespace MvcSample
var services = MvcServices.GetDefaultServices(configuration, _env);
var serviceProvider = new ServiceProvider().Add(services);
serviceProvider.AddInstance<PassThroughAttribute>(new PassThroughAttribute());
var routes = new RouteCollection()
{
DefaultHandler = new MvcApplication(serviceProvider),

View File

@ -12,7 +12,7 @@
<p><a href="http://asp.net" class="btn btn-primary btn-large">Learn more &raquo;</a></p>
</div>
<div class="row">
<h3 title="@Model.Name" class="@nullValue">Hello @Model.Name!</h3>
<h3 title="@Model.Name" class="@nullValue">Hello @Model.Name! Happy @Model.Age birthday.</h3>
<div class="col-md-4">
<h2>Getting started</h2>

View File

@ -5,10 +5,13 @@ namespace Microsoft.AspNet.Mvc
{
public class ActionFilterContext
{
public ActionFilterContext(ActionContext actionContext, IDictionary<string, object> actionParameters)
public ActionFilterContext(ActionContext actionContext,
IDictionary<string, object> actionParameters,
Type methodReturnType)
{
ActionContext = actionContext;
ActionParameters = actionParameters;
MethodReturnType = methodReturnType;
}
public virtual IDictionary<string, object> ActionParameters { get; private set; }
@ -17,6 +20,6 @@ namespace Microsoft.AspNet.Mvc
public virtual Type MethodReturnType { get; private set; }
public virtual object Result { get; set; }
public virtual IActionResult Result { get; set; }
}
}

View File

@ -46,9 +46,6 @@ namespace Microsoft.AspNet.Mvc
var controllerAttributes = cd.ControllerTypeInfo.GetCustomAttributes(inherit: true).ToArray();
var filtersFromController = GetOrderedFilterAttributes(controllerAttributes);
bool allowAnonymous = IsAnonymous(controllerAttributes);
bool allowAnonymous = IsAnonymous(controllerAttributes);
foreach (var methodInfo in cd.ControllerTypeInfo.DeclaredMethods)

View File

@ -66,21 +66,40 @@ namespace Microsoft.AspNet.Mvc
var parameterValues = await GetParameterValues(modelState);
var authZFilters = context.AuthorizationFilters;
var authZEndPoint = new AuthorizationFilterEndPoint();
authZFilters.Add(authZEndPoint);
var authZContext = new AuthorizationFilterContext(_actionContext);
var authZPipeline = new FilterPipelineBuilder<AuthorizationFilterContext>(authZFilters, authZContext);
await authZPipeline.InvokeAsync();
if (authZContext.ActionResult == null &&
!authZContext.HasFailed &&
authZEndPoint.EndPointCalled)
bool authZPassed;
if (authZFilters != null && authZFilters.Count > 0)
{
var actionFilters = context.ActionFilters;
var authZEndPoint = new AuthorizationFilterEndPoint();
authZFilters.Add(authZEndPoint);
var authZContext = new AuthorizationFilterContext(_actionContext);
var authZPipeline = new FilterPipelineBuilder<AuthorizationFilterContext>(authZFilters,
authZContext);
await authZPipeline.InvokeAsync();
if (authZContext.ActionResult == null &&
!authZContext.HasFailed &&
authZEndPoint.EndPointCalled)
{
actionResult = null;
}
else
{
actionResult = authZContext.ActionResult ?? new HttpStatusCodeResult(401);
}
}
else
{
actionResult = null;
}
if (actionResult == null)
{
var actionFilters = context.ActionFilters ?? new List<IActionFilter>();
var actionFilterContext = new ActionFilterContext(_actionContext,
new Dictionary<string, object>());
parameterValues,
method.ReturnType);
// TODO: This is extremely temporary and is going to get soon replaced with the action executer
var actionEndPoint = new ReflectedActionFilterEndPoint(async (inArray) => method.Invoke(controller, inArray),
@ -93,18 +112,12 @@ namespace Microsoft.AspNet.Mvc
await actionFilterPipeline.InvokeAsync();
object actionReturnValue = method.Invoke(controller, null);
actionResult = _actionResultFactory.CreateActionResult(method.ReturnType, actionReturnValue, _actionContext);
}
else
{
actionResult = authZContext.ActionResult ?? new HttpStatusCodeResult(401);
actionResult = (IActionResult)actionFilterContext.Result;
}
}
}
var actionResultFilters = context.ActionResultFilters;
await actionResult.ExecuteResultAsync(_actionContext);
var actionResultFilters = context.ActionResultFilters ?? new List<IActionResultFilter>();
var actionResultFilterContext = new ActionResultFilterContext(_actionContext, actionResult);
var actionResultFilterEndPoint = new ActionResultFilterEndPoint();
actionResultFilters.Add(actionResultFilterEndPoint);

View File

@ -51,7 +51,7 @@ namespace Microsoft.AspNet.Mvc
yield return DescribeService<INestedProvider<ActionDescriptorProviderContext>,
ReflectedActionDescriptorProvider>(configuration);
yield return DescribeService<INestedProvider<ActionInvokerProviderContext>,
ActionInvokerProvider>(configuration);
ReflectedActionInvokerProvider>(configuration);
yield return DescribeService<IModelMetadataProvider, DataAnnotationsModelMetadataProvider>(configuration);
yield return DescribeService<IActionBindingContextProvider, DefaultActionBindingContextProvider>(configuration);