Action filters & Authorization Filters working
This commit is contained in:
parent
6fed92695b
commit
772f833dc9
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
using System;
|
using Microsoft.AspNet.Mvc;
|
||||||
using System.Threading.Tasks;
|
using MvcSample.Filters;
|
||||||
using Microsoft.AspNet.Mvc;
|
|
||||||
using MvcSample.Models;
|
using MvcSample.Models;
|
||||||
|
|
||||||
namespace MvcSample
|
namespace MvcSample
|
||||||
{
|
{
|
||||||
// Expected order in descriptor - object -> int -> string
|
// Expected order in descriptor - object -> int -> string
|
||||||
// TODO: Add a real filter here
|
// TODO: Add a real filter here
|
||||||
[ServiceFilter(typeof(object), Order = 1)]
|
[ServiceFilter(typeof(PassThroughAttribute), Order = 1)]
|
||||||
[ServiceFilter(typeof(string))]
|
[ServiceFilter(typeof(PassThroughAttribute))]
|
||||||
[PassThrough(Order = 0)]
|
[PassThrough(Order = 0)]
|
||||||
[PassThrough(Order = 2)]
|
[PassThrough(Order = 2)]
|
||||||
public class FiltersController : Controller
|
public class FiltersController : Controller
|
||||||
|
|
@ -16,18 +15,13 @@ namespace MvcSample
|
||||||
private readonly User _user = new User() { Name = "User Name", Address = "Home Address" };
|
private readonly User _user = new User() { Name = "User Name", Address = "Home Address" };
|
||||||
|
|
||||||
// TODO: Add a real filter here
|
// TODO: Add a real filter here
|
||||||
[ServiceFilter(typeof(int))]
|
[ServiceFilter(typeof(PassThroughAttribute))]
|
||||||
public IActionResult Index()
|
[AgeEnhancer]
|
||||||
|
public IActionResult Index(int age)
|
||||||
{
|
{
|
||||||
|
_user.Age = age;
|
||||||
|
|
||||||
return View("MyView", _user);
|
return View("MyView", _user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PassThroughAttribute : AuthorizationFilterAttribute
|
|
||||||
{
|
|
||||||
public async override Task Invoke(AuthorizationFilterContext context, Func<Task> next)
|
|
||||||
{
|
|
||||||
await next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,5 +4,6 @@
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Address { get; set; }
|
public string Address { get; set; }
|
||||||
|
public int Age { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -36,6 +36,8 @@ namespace MvcSample
|
||||||
var services = MvcServices.GetDefaultServices(configuration, _env);
|
var services = MvcServices.GetDefaultServices(configuration, _env);
|
||||||
var serviceProvider = new ServiceProvider().Add(services);
|
var serviceProvider = new ServiceProvider().Add(services);
|
||||||
|
|
||||||
|
serviceProvider.AddInstance<PassThroughAttribute>(new PassThroughAttribute());
|
||||||
|
|
||||||
var routes = new RouteCollection()
|
var routes = new RouteCollection()
|
||||||
{
|
{
|
||||||
DefaultHandler = new MvcApplication(serviceProvider),
|
DefaultHandler = new MvcApplication(serviceProvider),
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
<p><a href="http://asp.net" class="btn btn-primary btn-large">Learn more »</a></p>
|
<p><a href="http://asp.net" class="btn btn-primary btn-large">Learn more »</a></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<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">
|
<div class="col-md-4">
|
||||||
<h2>Getting started</h2>
|
<h2>Getting started</h2>
|
||||||
|
|
@ -5,10 +5,13 @@ namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
public class ActionFilterContext
|
public class ActionFilterContext
|
||||||
{
|
{
|
||||||
public ActionFilterContext(ActionContext actionContext, IDictionary<string, object> actionParameters)
|
public ActionFilterContext(ActionContext actionContext,
|
||||||
|
IDictionary<string, object> actionParameters,
|
||||||
|
Type methodReturnType)
|
||||||
{
|
{
|
||||||
ActionContext = actionContext;
|
ActionContext = actionContext;
|
||||||
ActionParameters = actionParameters;
|
ActionParameters = actionParameters;
|
||||||
|
MethodReturnType = methodReturnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual IDictionary<string, object> ActionParameters { get; private set; }
|
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 Type MethodReturnType { get; private set; }
|
||||||
|
|
||||||
public virtual object Result { get; set; }
|
public virtual IActionResult Result { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,6 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var controllerAttributes = cd.ControllerTypeInfo.GetCustomAttributes(inherit: true).ToArray();
|
var controllerAttributes = cd.ControllerTypeInfo.GetCustomAttributes(inherit: true).ToArray();
|
||||||
var filtersFromController = GetOrderedFilterAttributes(controllerAttributes);
|
var filtersFromController = GetOrderedFilterAttributes(controllerAttributes);
|
||||||
|
|
||||||
bool allowAnonymous = IsAnonymous(controllerAttributes);
|
|
||||||
|
|
||||||
|
|
||||||
bool allowAnonymous = IsAnonymous(controllerAttributes);
|
bool allowAnonymous = IsAnonymous(controllerAttributes);
|
||||||
|
|
||||||
foreach (var methodInfo in cd.ControllerTypeInfo.DeclaredMethods)
|
foreach (var methodInfo in cd.ControllerTypeInfo.DeclaredMethods)
|
||||||
|
|
|
||||||
|
|
@ -66,21 +66,40 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var parameterValues = await GetParameterValues(modelState);
|
var parameterValues = await GetParameterValues(modelState);
|
||||||
|
|
||||||
var authZFilters = context.AuthorizationFilters;
|
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();
|
bool authZPassed;
|
||||||
|
if (authZFilters != null && authZFilters.Count > 0)
|
||||||
|
|
||||||
if (authZContext.ActionResult == null &&
|
|
||||||
!authZContext.HasFailed &&
|
|
||||||
authZEndPoint.EndPointCalled)
|
|
||||||
{
|
{
|
||||||
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,
|
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
|
// 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),
|
var actionEndPoint = new ReflectedActionFilterEndPoint(async (inArray) => method.Invoke(controller, inArray),
|
||||||
|
|
@ -93,18 +112,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
|
|
||||||
await actionFilterPipeline.InvokeAsync();
|
await actionFilterPipeline.InvokeAsync();
|
||||||
|
|
||||||
object actionReturnValue = method.Invoke(controller, null);
|
actionResult = (IActionResult)actionFilterContext.Result;
|
||||||
actionResult = _actionResultFactory.CreateActionResult(method.ReturnType, actionReturnValue, _actionContext);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
actionResult = authZContext.ActionResult ?? new HttpStatusCodeResult(401);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var actionResultFilters = context.ActionResultFilters;
|
var actionResultFilters = context.ActionResultFilters ?? new List<IActionResultFilter>();
|
||||||
await actionResult.ExecuteResultAsync(_actionContext);
|
|
||||||
var actionResultFilterContext = new ActionResultFilterContext(_actionContext, actionResult);
|
var actionResultFilterContext = new ActionResultFilterContext(_actionContext, actionResult);
|
||||||
var actionResultFilterEndPoint = new ActionResultFilterEndPoint();
|
var actionResultFilterEndPoint = new ActionResultFilterEndPoint();
|
||||||
actionResultFilters.Add(actionResultFilterEndPoint);
|
actionResultFilters.Add(actionResultFilterEndPoint);
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
yield return DescribeService<INestedProvider<ActionDescriptorProviderContext>,
|
yield return DescribeService<INestedProvider<ActionDescriptorProviderContext>,
|
||||||
ReflectedActionDescriptorProvider>(configuration);
|
ReflectedActionDescriptorProvider>(configuration);
|
||||||
yield return DescribeService<INestedProvider<ActionInvokerProviderContext>,
|
yield return DescribeService<INestedProvider<ActionInvokerProviderContext>,
|
||||||
ActionInvokerProvider>(configuration);
|
ReflectedActionInvokerProvider>(configuration);
|
||||||
|
|
||||||
yield return DescribeService<IModelMetadataProvider, DataAnnotationsModelMetadataProvider>(configuration);
|
yield return DescribeService<IModelMetadataProvider, DataAnnotationsModelMetadataProvider>(configuration);
|
||||||
yield return DescribeService<IActionBindingContextProvider, DefaultActionBindingContextProvider>(configuration);
|
yield return DescribeService<IActionBindingContextProvider, DefaultActionBindingContextProvider>(configuration);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue