Adding Resource Filters
This is a new filter stage that surrounds the existing model binding, action, and result parts of the pipeline. Resource Filters run after Authorization Filters. The other major change is to support one of the primary scenarios for Resource Filters. We want a filter to be able to modify the inputs the model binding (formatters, model binders, value providers, etc) -- this means that those changes need to be held on a context object and preserved so that they can be used in the controller. So, IActionBindingContextProvider is removed - the ActionBindingContext will be created by the invoker. For now it will be part of the action context.
This commit is contained in:
parent
990473aebc
commit
5ac5c53c09
|
|
@ -40,12 +40,6 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
public ActionDescriptor ActionDescriptor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Input formatters associated with this context.
|
||||
/// The formatters are populated only after IInputFormattersProvider runs.
|
||||
/// </summary>
|
||||
public IList<IInputFormatter> InputFormatters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The controller is available only after the controller factory runs.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -92,10 +92,13 @@ namespace Microsoft.AspNet.Mvc
|
|||
public ActionContext ActionContext { get; set; }
|
||||
|
||||
[Activate]
|
||||
public IUrlHelper Url { get; set; }
|
||||
public ActionBindingContext BindingContext { get; set; }
|
||||
|
||||
[Activate]
|
||||
public IActionBindingContextProvider BindingContextProvider { get; set; }
|
||||
public IModelMetadataProvider MetadataProvider { get; set; }
|
||||
|
||||
[Activate]
|
||||
public IUrlHelper Url { get; set; }
|
||||
|
||||
public IPrincipal User
|
||||
{
|
||||
|
|
@ -701,7 +704,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
[NonAction]
|
||||
public virtual CreatedAtActionResult CreatedAtAction(string actionName, object routeValues, object value)
|
||||
{
|
||||
return CreatedAtAction(actionName, controllerName: null, routeValues: routeValues, value: value);
|
||||
return CreatedAtAction(actionName, controllerName: null, routeValues: routeValues, value: value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -810,7 +813,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
|
||||
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
|
|
@ -823,19 +826,19 @@ namespace Microsoft.AspNet.Mvc
|
|||
[NotNull] string prefix)
|
||||
where TModel : class
|
||||
{
|
||||
if (BindingContextProvider == null)
|
||||
if (BindingContext == null)
|
||||
{
|
||||
var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider),
|
||||
GetType().FullName);
|
||||
var message = Resources.FormatPropertyOfTypeCannotBeNull(
|
||||
nameof(BindingContext),
|
||||
typeof(Controller).FullName);
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
var bindingContext = await BindingContextProvider.GetActionBindingContextAsync(ActionContext);
|
||||
return await TryUpdateModelAsync(model, prefix, bindingContext.ValueProvider);
|
||||
return await TryUpdateModelAsync(model, prefix, BindingContext.ValueProvider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
|
|
@ -850,33 +853,34 @@ namespace Microsoft.AspNet.Mvc
|
|||
[NotNull] IValueProvider valueProvider)
|
||||
where TModel : class
|
||||
{
|
||||
if (BindingContextProvider == null)
|
||||
if (BindingContext == null)
|
||||
{
|
||||
var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider),
|
||||
GetType().FullName);
|
||||
var message = Resources.FormatPropertyOfTypeCannotBeNull(
|
||||
nameof(BindingContext),
|
||||
typeof(Controller).FullName);
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
var bindingContext = await BindingContextProvider.GetActionBindingContextAsync(ActionContext);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(model,
|
||||
prefix,
|
||||
ActionContext.HttpContext,
|
||||
ModelState,
|
||||
bindingContext.MetadataProvider,
|
||||
bindingContext.ModelBinder,
|
||||
valueProvider,
|
||||
bindingContext.ValidatorProvider);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
prefix,
|
||||
ActionContext.HttpContext,
|
||||
ModelState,
|
||||
MetadataProvider,
|
||||
BindingContext.ModelBinder,
|
||||
valueProvider,
|
||||
BindingContext.ValidatorProvider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
|
||||
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="prefix">The prefix to use when looking up values in the current <see cref="IValueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
|
||||
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
|
||||
/// which need to be included for the current model.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
|
||||
[NonAction]
|
||||
|
|
@ -886,27 +890,28 @@ namespace Microsoft.AspNet.Mvc
|
|||
[NotNull] params Expression<Func<TModel, object>>[] includeExpressions)
|
||||
where TModel : class
|
||||
{
|
||||
if (BindingContextProvider == null)
|
||||
if (BindingContext == null)
|
||||
{
|
||||
var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider),
|
||||
GetType().FullName);
|
||||
var message = Resources.FormatPropertyOfTypeCannotBeNull(
|
||||
nameof(BindingContext),
|
||||
typeof(Controller).FullName);
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
var bindingContext = await BindingContextProvider.GetActionBindingContextAsync(ActionContext);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(model,
|
||||
prefix,
|
||||
ActionContext.HttpContext,
|
||||
ModelState,
|
||||
bindingContext.MetadataProvider,
|
||||
bindingContext.ModelBinder,
|
||||
bindingContext.ValueProvider,
|
||||
bindingContext.ValidatorProvider,
|
||||
includeExpressions);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
prefix,
|
||||
ActionContext.HttpContext,
|
||||
ModelState,
|
||||
MetadataProvider,
|
||||
BindingContext.ModelBinder,
|
||||
BindingContext.ValueProvider,
|
||||
BindingContext.ValidatorProvider,
|
||||
includeExpressions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
|
||||
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
|
|
@ -922,27 +927,28 @@ namespace Microsoft.AspNet.Mvc
|
|||
[NotNull] Func<ModelBindingContext, string, bool> predicate)
|
||||
where TModel : class
|
||||
{
|
||||
if (BindingContextProvider == null)
|
||||
if (BindingContext == null)
|
||||
{
|
||||
var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider),
|
||||
GetType().FullName);
|
||||
var message = Resources.FormatPropertyOfTypeCannotBeNull(
|
||||
nameof(BindingContext),
|
||||
typeof(Controller).FullName);
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
var bindingContext = await BindingContextProvider.GetActionBindingContextAsync(ActionContext);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(model,
|
||||
prefix,
|
||||
ActionContext.HttpContext,
|
||||
ModelState,
|
||||
bindingContext.MetadataProvider,
|
||||
bindingContext.ModelBinder,
|
||||
bindingContext.ValueProvider,
|
||||
bindingContext.ValidatorProvider,
|
||||
predicate);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
prefix,
|
||||
ActionContext.HttpContext,
|
||||
ModelState,
|
||||
MetadataProvider,
|
||||
BindingContext.ModelBinder,
|
||||
BindingContext.ValueProvider,
|
||||
BindingContext.ValidatorProvider,
|
||||
predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
|
|
@ -950,7 +956,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>
|
||||
/// </param>
|
||||
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
|
||||
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
|
||||
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
|
||||
/// which need to be included for the current model.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
|
||||
[NonAction]
|
||||
|
|
@ -961,27 +967,28 @@ namespace Microsoft.AspNet.Mvc
|
|||
[NotNull] params Expression<Func<TModel, object>>[] includeExpressions)
|
||||
where TModel : class
|
||||
{
|
||||
if (BindingContextProvider == null)
|
||||
if (BindingContext == null)
|
||||
{
|
||||
var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider),
|
||||
GetType().FullName);
|
||||
var message = Resources.FormatPropertyOfTypeCannotBeNull(
|
||||
nameof(BindingContext),
|
||||
typeof(Controller).FullName);
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
var bindingContext = await BindingContextProvider.GetActionBindingContextAsync(ActionContext);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(model,
|
||||
prefix,
|
||||
ActionContext.HttpContext,
|
||||
ModelState,
|
||||
bindingContext.MetadataProvider,
|
||||
bindingContext.ModelBinder,
|
||||
valueProvider,
|
||||
bindingContext.ValidatorProvider,
|
||||
includeExpressions);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
prefix,
|
||||
ActionContext.HttpContext,
|
||||
ModelState,
|
||||
MetadataProvider,
|
||||
BindingContext.ModelBinder,
|
||||
valueProvider,
|
||||
BindingContext.ValidatorProvider,
|
||||
includeExpressions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
|
|
@ -999,23 +1006,24 @@ namespace Microsoft.AspNet.Mvc
|
|||
[NotNull] Func<ModelBindingContext, string, bool> predicate)
|
||||
where TModel : class
|
||||
{
|
||||
if (BindingContextProvider == null)
|
||||
if (BindingContext == null)
|
||||
{
|
||||
var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider),
|
||||
GetType().FullName);
|
||||
var message = Resources.FormatPropertyOfTypeCannotBeNull(
|
||||
nameof(BindingContext),
|
||||
typeof(Controller).FullName);
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
var bindingContext = await BindingContextProvider.GetActionBindingContextAsync(ActionContext);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(model,
|
||||
prefix,
|
||||
ActionContext.HttpContext,
|
||||
ModelState,
|
||||
bindingContext.MetadataProvider,
|
||||
bindingContext.ModelBinder,
|
||||
valueProvider,
|
||||
bindingContext.ValidatorProvider,
|
||||
predicate);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
prefix,
|
||||
ActionContext.HttpContext,
|
||||
ModelState,
|
||||
MetadataProvider,
|
||||
BindingContext.ModelBinder,
|
||||
valueProvider,
|
||||
BindingContext.ValidatorProvider,
|
||||
predicate);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
|
|
@ -14,21 +15,36 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
private readonly ControllerActionDescriptor _descriptor;
|
||||
private readonly IControllerFactory _controllerFactory;
|
||||
private readonly IInputFormattersProvider _inputFormattersProvider;
|
||||
private readonly IControllerActionArgumentBinder _actionInvocationProvider;
|
||||
private readonly IControllerActionArgumentBinder _argumentBinder;
|
||||
|
||||
public ControllerActionInvoker([NotNull] ActionContext actionContext,
|
||||
[NotNull] INestedProviderManager<FilterProviderContext> filterProvider,
|
||||
[NotNull] IControllerFactory controllerFactory,
|
||||
[NotNull] ControllerActionDescriptor descriptor,
|
||||
[NotNull] IInputFormattersProvider inputFormattersProvider,
|
||||
[NotNull] IControllerActionArgumentBinder controllerActionArgumentBinder)
|
||||
: base(actionContext, filterProvider)
|
||||
public ControllerActionInvoker(
|
||||
[NotNull] ActionContext actionContext,
|
||||
[NotNull] INestedProviderManager<FilterProviderContext> filterProvider,
|
||||
[NotNull] IControllerFactory controllerFactory,
|
||||
[NotNull] ControllerActionDescriptor descriptor,
|
||||
[NotNull] IModelMetadataProvider modelMetadataProvider,
|
||||
[NotNull] IInputFormattersProvider inputFormatterProvider,
|
||||
[NotNull] IInputFormatterSelector inputFormatterSelector,
|
||||
[NotNull] IControllerActionArgumentBinder controllerActionArgumentBinder,
|
||||
[NotNull] IModelBinderProvider modelBinderProvider,
|
||||
[NotNull] IModelValidatorProviderProvider modelValidatorProviderProvider,
|
||||
[NotNull] IValueProviderFactoryProvider valueProviderFactoryProvider,
|
||||
[NotNull] IScopedInstance<ActionBindingContext> actionBindingContextAccessor)
|
||||
: base(
|
||||
actionContext,
|
||||
filterProvider,
|
||||
modelMetadataProvider,
|
||||
inputFormatterProvider,
|
||||
inputFormatterSelector,
|
||||
modelBinderProvider,
|
||||
modelValidatorProviderProvider,
|
||||
valueProviderFactoryProvider,
|
||||
actionBindingContextAccessor)
|
||||
{
|
||||
_descriptor = descriptor;
|
||||
_controllerFactory = controllerFactory;
|
||||
_inputFormattersProvider = inputFormattersProvider;
|
||||
_actionInvocationProvider = controllerActionArgumentBinder;
|
||||
_argumentBinder = controllerActionArgumentBinder;
|
||||
|
||||
if (descriptor.MethodInfo == null)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
|
|
@ -40,12 +56,13 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
public async override Task InvokeAsync()
|
||||
{
|
||||
// The binding context is used in activation
|
||||
Debug.Assert(ActionBindingContext != null);
|
||||
var controller = _controllerFactory.CreateController(ActionContext);
|
||||
|
||||
try
|
||||
{
|
||||
ActionContext.Controller = controller;
|
||||
ActionContext.InputFormatters = _inputFormattersProvider.InputFormatters
|
||||
.ToList();
|
||||
await base.InvokeAsync();
|
||||
}
|
||||
finally
|
||||
|
|
@ -68,9 +85,11 @@ namespace Microsoft.AspNet.Mvc
|
|||
return actionResult;
|
||||
}
|
||||
|
||||
protected override Task<IDictionary<string, object>> GetActionArgumentsAsync(ActionContext context)
|
||||
protected override Task<IDictionary<string, object>> GetActionArgumentsAsync(
|
||||
ActionContext context,
|
||||
ActionBindingContext bindingContext)
|
||||
{
|
||||
return _actionInvocationProvider.GetActionArgumentsAsync(context);
|
||||
return _argumentBinder.GetActionArgumentsAsync(context, bindingContext);
|
||||
}
|
||||
|
||||
// Marking as internal for Unit Testing purposes.
|
||||
|
|
|
|||
|
|
@ -2,26 +2,46 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class ControllerActionInvokerProvider : IActionInvokerProvider
|
||||
{
|
||||
private readonly IControllerActionArgumentBinder _argumentBinder;
|
||||
private readonly IControllerFactory _controllerFactory;
|
||||
private readonly IInputFormattersProvider _inputFormattersProvider;
|
||||
private readonly INestedProviderManager<FilterProviderContext> _filterProvider;
|
||||
private readonly IControllerActionArgumentBinder _actionInvocationInfoProvider;
|
||||
private readonly IInputFormattersProvider _inputFormattersProvider;
|
||||
private readonly IInputFormatterSelector _inputFormatterSelector;
|
||||
private readonly IModelBinderProvider _modelBinderProvider;
|
||||
private readonly IModelMetadataProvider _modelMetadataProvider;
|
||||
private readonly IModelValidatorProviderProvider _modelValidationProviderProvider;
|
||||
private readonly IValueProviderFactoryProvider _valueProviderFactoryProvider;
|
||||
private readonly IScopedInstance<ActionBindingContext> _actionBindingContextAccessor;
|
||||
|
||||
public ControllerActionInvokerProvider(IControllerFactory controllerFactory,
|
||||
IInputFormattersProvider inputFormattersProvider,
|
||||
INestedProviderManager<FilterProviderContext> filterProvider,
|
||||
IControllerActionArgumentBinder actionInvocationInfoProvider)
|
||||
public ControllerActionInvokerProvider(
|
||||
IControllerFactory controllerFactory,
|
||||
IInputFormattersProvider inputFormattersProvider,
|
||||
INestedProviderManager<FilterProviderContext> filterProvider,
|
||||
IControllerActionArgumentBinder argumentBinder,
|
||||
IModelMetadataProvider modelMetadataProvider,
|
||||
IInputFormatterSelector inputFormatterSelector,
|
||||
IModelBinderProvider modelBinderProvider,
|
||||
IModelValidatorProviderProvider modelValidationProviderProvider,
|
||||
IValueProviderFactoryProvider valueProviderFactoryProvider,
|
||||
IScopedInstance<ActionBindingContext> actionBindingContextAccessor)
|
||||
{
|
||||
_controllerFactory = controllerFactory;
|
||||
_inputFormattersProvider = inputFormattersProvider;
|
||||
_filterProvider = filterProvider;
|
||||
_actionInvocationInfoProvider = actionInvocationInfoProvider;
|
||||
_argumentBinder = argumentBinder;
|
||||
_modelMetadataProvider = modelMetadataProvider;
|
||||
_modelBinderProvider = modelBinderProvider;
|
||||
_inputFormatterSelector = inputFormatterSelector;
|
||||
_modelValidationProviderProvider = modelValidationProviderProvider;
|
||||
_valueProviderFactoryProvider = valueProviderFactoryProvider;
|
||||
_actionBindingContextAccessor = actionBindingContextAccessor;
|
||||
}
|
||||
|
||||
public int Order
|
||||
|
|
@ -40,8 +60,14 @@ namespace Microsoft.AspNet.Mvc
|
|||
_filterProvider,
|
||||
_controllerFactory,
|
||||
actionDescriptor,
|
||||
_modelMetadataProvider,
|
||||
_inputFormattersProvider,
|
||||
_actionInvocationInfoProvider);
|
||||
_inputFormatterSelector,
|
||||
_argumentBinder,
|
||||
_modelBinderProvider,
|
||||
_modelValidationProviderProvider,
|
||||
_valueProviderFactoryProvider,
|
||||
_actionBindingContextAccessor);
|
||||
}
|
||||
|
||||
callNext();
|
||||
|
|
|
|||
|
|
@ -15,18 +15,17 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// </summary>
|
||||
public class DefaultControllerActionArgumentBinder : IControllerActionArgumentBinder
|
||||
{
|
||||
private readonly IActionBindingContextProvider _bindingContextProvider;
|
||||
private readonly IModelMetadataProvider _modelMetadataProvider;
|
||||
|
||||
public DefaultControllerActionArgumentBinder(IActionBindingContextProvider bindingContextProvider)
|
||||
public DefaultControllerActionArgumentBinder(IModelMetadataProvider modelMetadataProvider)
|
||||
{
|
||||
_bindingContextProvider = bindingContextProvider;
|
||||
_modelMetadataProvider = modelMetadataProvider;
|
||||
}
|
||||
|
||||
public async Task<IDictionary<string, object>> GetActionArgumentsAsync(ActionContext actionContext)
|
||||
public async Task<IDictionary<string, object>> GetActionArgumentsAsync(
|
||||
ActionContext actionContext,
|
||||
ActionBindingContext actionBindingContext)
|
||||
{
|
||||
var actionBindingContext = await _bindingContextProvider.GetActionBindingContextAsync(actionContext);
|
||||
var metadataProvider = actionBindingContext.MetadataProvider;
|
||||
|
||||
var actionDescriptor = actionContext.ActionDescriptor as ControllerActionDescriptor;
|
||||
if (actionDescriptor == null)
|
||||
{
|
||||
|
|
@ -39,7 +38,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
var parameterMetadata = new List<ModelMetadata>();
|
||||
foreach (var parameter in actionDescriptor.Parameters)
|
||||
{
|
||||
var metadata = metadataProvider.GetMetadataForParameter(
|
||||
var metadata = _modelMetadataProvider.GetMetadataForParameter(
|
||||
modelAccessor: null,
|
||||
methodInfo: actionDescriptor.MethodInfo,
|
||||
parameterName: parameter.Name);
|
||||
|
|
@ -52,7 +51,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
|
||||
var actionArguments = new Dictionary<string, object>(StringComparer.Ordinal);
|
||||
await PopulateArgumentAsync(actionBindingContext, actionArguments, parameterMetadata);
|
||||
await PopulateArgumentAsync(actionContext, actionBindingContext, actionArguments, parameterMetadata);
|
||||
return actionArguments;
|
||||
}
|
||||
|
||||
|
|
@ -71,25 +70,25 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
|
||||
private async Task PopulateArgumentAsync(
|
||||
ActionBindingContext actionBindingContext,
|
||||
ActionContext actionContext,
|
||||
ActionBindingContext bindingContext,
|
||||
IDictionary<string, object> arguments,
|
||||
IEnumerable<ModelMetadata> parameterMetadata)
|
||||
{
|
||||
var operationBindingContext = new OperationBindingContext
|
||||
{
|
||||
ModelBinder = actionBindingContext.ModelBinder,
|
||||
ValidatorProvider = actionBindingContext.ValidatorProvider,
|
||||
MetadataProvider = actionBindingContext.MetadataProvider,
|
||||
HttpContext = actionBindingContext.ActionContext.HttpContext,
|
||||
ValueProvider = actionBindingContext.ValueProvider,
|
||||
ModelBinder = bindingContext.ModelBinder,
|
||||
ValidatorProvider = bindingContext.ValidatorProvider,
|
||||
MetadataProvider = _modelMetadataProvider,
|
||||
HttpContext = actionContext.HttpContext,
|
||||
ValueProvider = bindingContext.ValueProvider,
|
||||
};
|
||||
|
||||
foreach (var parameter in parameterMetadata)
|
||||
{
|
||||
var parameterType = parameter.ModelType;
|
||||
var modelBindingContext =
|
||||
GetModelBindingContext(parameter, actionBindingContext, operationBindingContext);
|
||||
if (await actionBindingContext.ModelBinder.BindModelAsync(modelBindingContext))
|
||||
var modelBindingContext = GetModelBindingContext(parameter, actionContext, operationBindingContext);
|
||||
if (await bindingContext.ModelBinder.BindModelAsync(modelBindingContext))
|
||||
{
|
||||
arguments[parameter.PropertyName] = modelBindingContext.Model;
|
||||
}
|
||||
|
|
@ -98,18 +97,18 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
internal static ModelBindingContext GetModelBindingContext(
|
||||
ModelMetadata modelMetadata,
|
||||
ActionBindingContext actionBindingContext,
|
||||
ActionContext actionContext,
|
||||
OperationBindingContext operationBindingContext)
|
||||
{
|
||||
var modelBindingContext = new ModelBindingContext
|
||||
{
|
||||
ModelName = modelMetadata.BinderModelName ?? modelMetadata.PropertyName,
|
||||
ModelMetadata = modelMetadata,
|
||||
ModelState = actionBindingContext.ActionContext.ModelState,
|
||||
ModelState = actionContext.ModelState,
|
||||
|
||||
// Fallback only if there is no explicit model name set.
|
||||
FallbackToEmptyPrefix = modelMetadata.BinderModelName == null,
|
||||
ValueProvider = actionBindingContext.ValueProvider,
|
||||
ValueProvider = operationBindingContext.ValueProvider,
|
||||
OperationBindingContext = operationBindingContext,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,15 @@ namespace Microsoft.AspNet.Mvc
|
|||
serviceProvider.GetRequiredService<IModelMetadataProvider>(),
|
||||
context.ModelState);
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(ActionBindingContext),
|
||||
(context) =>
|
||||
{
|
||||
var serviceProvider = context.HttpContext.RequestServices;
|
||||
var accessor = serviceProvider.GetRequiredService<IScopedInstance<ActionBindingContext>>();
|
||||
return accessor.Value;
|
||||
}
|
||||
}
|
||||
};
|
||||
return dictionary;
|
||||
|
|
|
|||
|
|
@ -8,21 +8,32 @@ using System.Linq;
|
|||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public abstract class FilterActionInvoker : IActionInvoker
|
||||
{
|
||||
private readonly IModelMetadataProvider _modelMetadataProvider;
|
||||
private readonly INestedProviderManager<FilterProviderContext> _filterProvider;
|
||||
private readonly IInputFormattersProvider _inputFormatterProvider;
|
||||
private readonly IInputFormatterSelector _inputFormatterSelector;
|
||||
private readonly IModelBinderProvider _modelBinderProvider;
|
||||
private readonly IModelValidatorProviderProvider _modelValidatorProviderProvider;
|
||||
private readonly IValueProviderFactoryProvider _valueProviderFactoryProvider;
|
||||
private readonly IScopedInstance<ActionBindingContext> _actionBindingContextAccessor;
|
||||
|
||||
private IFilter[] _filters;
|
||||
private FilterCursor _cursor;
|
||||
|
||||
private ExceptionContext _exceptionContext;
|
||||
|
||||
private AuthorizationContext _authorizationContext;
|
||||
|
||||
private ResourceExecutingContext _resourceExecutingContext;
|
||||
private ResourceExecutedContext _resourceExecutedContext;
|
||||
|
||||
private ExceptionContext _exceptionContext;
|
||||
|
||||
private ActionExecutingContext _actionExecutingContext;
|
||||
private ActionExecutedContext _actionExecutedContext;
|
||||
|
||||
|
|
@ -31,17 +42,48 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
public FilterActionInvoker(
|
||||
[NotNull] ActionContext actionContext,
|
||||
[NotNull] INestedProviderManager<FilterProviderContext> filterProvider)
|
||||
[NotNull] INestedProviderManager<FilterProviderContext> filterProvider,
|
||||
[NotNull] IModelMetadataProvider modelMetadataProvider,
|
||||
[NotNull] IInputFormattersProvider inputFormatterProvider,
|
||||
[NotNull] IInputFormatterSelector inputFormatterSelector,
|
||||
[NotNull] IModelBinderProvider modelBinderProvider,
|
||||
[NotNull] IModelValidatorProviderProvider modelValidatorProviderProvider,
|
||||
[NotNull] IValueProviderFactoryProvider valueProviderFactoryProvider,
|
||||
[NotNull] IScopedInstance<ActionBindingContext> actionBindingContextAccessor)
|
||||
{
|
||||
ActionContext = actionContext;
|
||||
|
||||
_filterProvider = filterProvider;
|
||||
_modelMetadataProvider = modelMetadataProvider;
|
||||
_inputFormatterProvider = inputFormatterProvider;
|
||||
_inputFormatterSelector = inputFormatterSelector;
|
||||
_modelBinderProvider = modelBinderProvider;
|
||||
_modelValidatorProviderProvider = modelValidatorProviderProvider;
|
||||
_valueProviderFactoryProvider = valueProviderFactoryProvider;
|
||||
_actionBindingContextAccessor = actionBindingContextAccessor;
|
||||
|
||||
ActionBindingContext = new ActionBindingContext();
|
||||
}
|
||||
|
||||
protected ActionContext ActionContext { get; private set; }
|
||||
|
||||
protected ActionBindingContext ActionBindingContext
|
||||
{
|
||||
get
|
||||
{
|
||||
return _actionBindingContextAccessor.Value;
|
||||
}
|
||||
private set
|
||||
{
|
||||
_actionBindingContextAccessor.Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Task<IActionResult> InvokeActionAsync(ActionExecutingContext actionExecutingContext);
|
||||
|
||||
protected abstract Task<IDictionary<string, object>> GetActionArgumentsAsync([NotNull] ActionContext context);
|
||||
protected abstract Task<IDictionary<string, object>> GetActionArgumentsAsync(
|
||||
[NotNull] ActionContext context,
|
||||
[NotNull] ActionBindingContext bindingContext);
|
||||
|
||||
public virtual async Task InvokeAsync()
|
||||
{
|
||||
|
|
@ -59,38 +101,22 @@ namespace Microsoft.AspNet.Mvc
|
|||
return;
|
||||
}
|
||||
|
||||
// >> ExceptionFilters >> ActionFilters >> Action
|
||||
await InvokeAllExceptionFiltersAsync();
|
||||
await InvokeAllResourceFiltersAsync();
|
||||
|
||||
// If Exception Filters provide a result, it's a short-circuit due to an exception.
|
||||
// We don't execute Result Filters around the result.
|
||||
Debug.Assert(_exceptionContext != null);
|
||||
if (_exceptionContext.Result != null)
|
||||
// We've reached the end of resource filters. If there's an unhandled exception on the context then
|
||||
// it should be thrown and middleware has a chance to handle it.
|
||||
Debug.Assert(_resourceExecutedContext != null);
|
||||
if (_resourceExecutedContext.Exception != null && !_resourceExecutedContext.ExceptionHandled)
|
||||
{
|
||||
await _exceptionContext.Result.ExecuteResultAsync(ActionContext);
|
||||
}
|
||||
else if (_exceptionContext.Exception != null)
|
||||
{
|
||||
// If we get here, this means that we have an unhandled exception
|
||||
if (_exceptionContext.ExceptionDispatchInfo != null)
|
||||
if (_resourceExecutedContext.ExceptionDispatchInfo == null)
|
||||
{
|
||||
_exceptionContext.ExceptionDispatchInfo.Throw();
|
||||
throw _resourceExecutedContext.Exception;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw _exceptionContext.Exception;
|
||||
_resourceExecutedContext.ExceptionDispatchInfo.Throw();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have a successful 'result' from the action or an Action Filter, so run
|
||||
// Result Filters.
|
||||
Debug.Assert(_actionExecutedContext != null);
|
||||
var result = _actionExecutedContext.Result;
|
||||
|
||||
// >> ResultFilters >> (Result)
|
||||
await InvokeAllResultFiltersAsync(result);
|
||||
}
|
||||
}
|
||||
|
||||
private IFilter[] GetFilters()
|
||||
|
|
@ -146,6 +172,148 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
}
|
||||
|
||||
private async Task InvokeAllResourceFiltersAsync()
|
||||
{
|
||||
_cursor.SetStage(FilterStage.ResourceFilters);
|
||||
|
||||
var context = new ResourceExecutingContext(ActionContext, _filters);
|
||||
|
||||
context.InputFormatters = new List<IInputFormatter>(_inputFormatterProvider.InputFormatters);
|
||||
context.ModelBinders = new List<IModelBinder>(_modelBinderProvider.ModelBinders);
|
||||
|
||||
context.ValidatorProviders = new List<IModelValidatorProvider>(
|
||||
_modelValidatorProviderProvider.ModelValidatorProviders);
|
||||
|
||||
context.ValueProviderFactories = new List<IValueProviderFactory>(
|
||||
_valueProviderFactoryProvider.ValueProviderFactories);
|
||||
|
||||
_resourceExecutingContext = context;
|
||||
await InvokeResourceFilterAsync();
|
||||
}
|
||||
|
||||
private async Task<ResourceExecutedContext> InvokeResourceFilterAsync()
|
||||
{
|
||||
Debug.Assert(_resourceExecutingContext != null);
|
||||
|
||||
if (_resourceExecutingContext.Result != null)
|
||||
{
|
||||
// If we get here, it means that an async filter set a result AND called next(). This is forbidden.
|
||||
var message = Resources.FormatAsyncResourceFilter_InvalidShortCircuit(
|
||||
typeof(IAsyncResourceFilter).Name,
|
||||
nameof(ResourceExecutingContext.Result),
|
||||
typeof(ResourceExecutingContext).Name,
|
||||
typeof(ResourceExecutionDelegate).Name);
|
||||
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
var item = _cursor.GetNextFilter<IResourceFilter, IAsyncResourceFilter>();
|
||||
try
|
||||
{
|
||||
if (item.FilterAsync != null)
|
||||
{
|
||||
await item.FilterAsync.OnResourceExecutionAsync(
|
||||
_resourceExecutingContext,
|
||||
InvokeResourceFilterAsync);
|
||||
|
||||
if (_resourceExecutedContext == null)
|
||||
{
|
||||
// If we get here then the filter didn't call 'next' indicating a short circuit
|
||||
if (_resourceExecutingContext.Result != null)
|
||||
{
|
||||
await _resourceExecutingContext.Result.ExecuteResultAsync(ActionContext);
|
||||
}
|
||||
|
||||
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
|
||||
{
|
||||
Canceled = true,
|
||||
Result = _resourceExecutingContext.Result,
|
||||
};
|
||||
}
|
||||
}
|
||||
else if (item.Filter != null)
|
||||
{
|
||||
item.Filter.OnResourceExecuting(_resourceExecutingContext);
|
||||
|
||||
if (_resourceExecutingContext.Result != null)
|
||||
{
|
||||
// Short-circuited by setting a result.
|
||||
await _resourceExecutingContext.Result.ExecuteResultAsync(ActionContext);
|
||||
|
||||
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
|
||||
{
|
||||
Canceled = true,
|
||||
Result = _resourceExecutingContext.Result,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Filter.OnResourceExecuted(await InvokeResourceFilterAsync());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We've reached the end of resource filters, so move on to exception filters.
|
||||
|
||||
// >> ExceptionFilters >> Model Binding >> ActionFilters >> Action
|
||||
await InvokeAllExceptionFiltersAsync();
|
||||
|
||||
// If Exception Filters provide a result, it's a short-circuit due to an exception.
|
||||
// We don't execute Result Filters around the result.
|
||||
Debug.Assert(_exceptionContext != null);
|
||||
if (_exceptionContext.Result != null)
|
||||
{
|
||||
// This means that exception filters returned a result to 'handle' an error.
|
||||
// We're not interested in seeing the exception details since it was handled.
|
||||
await _exceptionContext.Result.ExecuteResultAsync(ActionContext);
|
||||
|
||||
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
|
||||
{
|
||||
Result = _exceptionContext.Result,
|
||||
};
|
||||
}
|
||||
else if (_exceptionContext.Exception != null)
|
||||
{
|
||||
// If we get here, this means that we have an unhandled exception.
|
||||
// Exception filted didn't handle this, so send it on to resource filters.
|
||||
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters);
|
||||
|
||||
// Preserve the stack trace if possible.
|
||||
_resourceExecutedContext.Exception = _exceptionContext.Exception;
|
||||
if (_exceptionContext.ExceptionDispatchInfo != null)
|
||||
{
|
||||
_resourceExecutedContext.ExceptionDispatchInfo = _exceptionContext.ExceptionDispatchInfo;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have a successful 'result' from the action or an Action Filter, so run
|
||||
// Result Filters.
|
||||
Debug.Assert(_actionExecutedContext != null);
|
||||
var result = _actionExecutedContext.Result;
|
||||
|
||||
// >> ResultFilters >> (Result)
|
||||
await InvokeAllResultFiltersAsync(result);
|
||||
|
||||
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
|
||||
{
|
||||
Result = _resultExecutedContext.Result,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
|
||||
{
|
||||
ExceptionDispatchInfo = ExceptionDispatchInfo.Capture(exception)
|
||||
};
|
||||
}
|
||||
|
||||
Debug.Assert(_resourceExecutedContext != null);
|
||||
return _resourceExecutedContext;
|
||||
}
|
||||
|
||||
private async Task InvokeAllExceptionFiltersAsync()
|
||||
{
|
||||
_cursor.SetStage(FilterStage.ExceptionFilters);
|
||||
|
|
@ -219,7 +387,25 @@ namespace Microsoft.AspNet.Mvc
|
|||
private async Task InvokeAllActionFiltersAsync()
|
||||
{
|
||||
_cursor.SetStage(FilterStage.ActionFilters);
|
||||
var arguments = await GetActionArgumentsAsync(ActionContext);
|
||||
|
||||
Debug.Assert(_resourceExecutingContext != null);
|
||||
|
||||
Debug.Assert(ActionBindingContext != null);
|
||||
ActionBindingContext.InputFormatters = _resourceExecutingContext.InputFormatters;
|
||||
ActionBindingContext.ModelBinder = new CompositeModelBinder(_resourceExecutingContext.ModelBinders);
|
||||
ActionBindingContext.ValidatorProvider = new CompositeModelValidatorProvider(
|
||||
_resourceExecutingContext.ValidatorProviders);
|
||||
|
||||
var valueProviderFactoryContext = new ValueProviderFactoryContext(
|
||||
ActionContext.HttpContext,
|
||||
ActionContext.RouteData.Values);
|
||||
|
||||
ActionBindingContext.ValueProvider = CompositeValueProvider.Create(
|
||||
_resourceExecutingContext.ValueProviderFactories,
|
||||
valueProviderFactoryContext);
|
||||
|
||||
var arguments = await GetActionArgumentsAsync(ActionContext, ActionBindingContext);
|
||||
|
||||
_actionExecutingContext = new ActionExecutingContext(ActionContext, _filters, arguments);
|
||||
await InvokeActionFilterAsync();
|
||||
}
|
||||
|
|
@ -232,7 +418,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
// If we get here, it means that an async filter set a result AND called next(). This is forbidden.
|
||||
var message = Resources.FormatAsyncActionFilter_InvalidShortCircuit(
|
||||
typeof(IAsyncActionFilter).Name,
|
||||
"Result",
|
||||
nameof(ActionExecutingContext.Result),
|
||||
typeof(ActionExecutingContext).Name,
|
||||
typeof(ActionExecutionDelegate).Name);
|
||||
|
||||
|
|
@ -325,7 +511,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
// This is forbidden.
|
||||
var message = Resources.FormatAsyncResultFilter_InvalidShortCircuit(
|
||||
typeof(IAsyncResultFilter).Name,
|
||||
"Cancel",
|
||||
nameof(ResultExecutingContext.Cancel),
|
||||
typeof(ResultExecutingContext).Name,
|
||||
typeof(ResultExecutionDelegate).Name);
|
||||
|
||||
|
|
@ -423,8 +609,9 @@ namespace Microsoft.AspNet.Mvc
|
|||
private enum FilterStage
|
||||
{
|
||||
Undefined,
|
||||
ExceptionFilters,
|
||||
AuthorizationFilters,
|
||||
ResourceFilters,
|
||||
ExceptionFilters,
|
||||
ActionFilters,
|
||||
ActionMethod,
|
||||
ResultFilters,
|
||||
|
|
|
|||
|
|
@ -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.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// A filter which surrounds execution of model binding, the action (and filters) and the action result
|
||||
/// (and filters).
|
||||
/// </summary>
|
||||
public interface IAsyncResourceFilter : IFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes the resource filter.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="ResourceExecutingContext"/>.</param>
|
||||
/// <param name="next">
|
||||
/// The <see cref="ResourceExecutionDelegate"/>. Invoked to execute the next
|
||||
/// resource filter, or the remainder of the pipeline.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Task"/> which will complete when the remainder of the pipeline completes.
|
||||
/// </returns>
|
||||
Task OnResourceExecutionAsync(
|
||||
[NotNull] ResourceExecutingContext context,
|
||||
[NotNull] ResourceExecutionDelegate next);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// A filter which surrounds execution of model binding, the action (and filters) and the action result
|
||||
/// (and filters).
|
||||
/// </summary>
|
||||
public interface IResourceFilter : IFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes the resource filter. Called before execution of the remainder of the pipeline.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="ResourceExecutingContext"/>.</param>
|
||||
void OnResourceExecuting([NotNull] ResourceExecutingContext context);
|
||||
|
||||
/// <summary>
|
||||
/// Executes the resource filter. Called after execution of the remainder of the pipeline.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="ResourceExecutedContext"/>.</param>
|
||||
void OnResourceExecuted([NotNull] ResourceExecutedContext context);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
// 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.Runtime.ExceptionServices;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// A context for resource filters.
|
||||
/// </summary>
|
||||
public class ResourceExecutedContext : FilterContext
|
||||
{
|
||||
private Exception _exception;
|
||||
private ExceptionDispatchInfo _exceptionDispatchInfo;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ResourceExecutedContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="actionContext">The <see cref="ActionContext"/>.</param>
|
||||
/// <param name="filters">The list of <see cref="IFilter"/> instances.</param>
|
||||
public ResourceExecutedContext(ActionContext actionContext, IList<IFilter> filters)
|
||||
: base(actionContext, filters)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value which indicates whether or not execution was canceled by a resource filter.
|
||||
/// If true, then a resource filter short-circuted execution by setting
|
||||
/// <see cref="ResourceExecutingContext.Result"/>.
|
||||
/// </summary>
|
||||
public virtual bool Canceled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or set the current <see cref="Exception"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Setting <see cref="Exception"/> or <see cref="ExceptionDispatchInfo"/> to <c>null</c> will treat
|
||||
/// the exception as handled, and it will not be rethrown by the runtime.
|
||||
///
|
||||
/// Setting <see cref="ExceptionHandled"/> to <c>true</c> will also mark the exception as handled.
|
||||
/// </remarks>
|
||||
public virtual Exception Exception
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_exception == null && _exceptionDispatchInfo != null)
|
||||
{
|
||||
return _exceptionDispatchInfo.SourceException;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _exception;
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_exceptionDispatchInfo = null;
|
||||
_exception = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or set the current <see cref="Exception"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Setting <see cref="Exception"/> or <see cref="ExceptionDispatchInfo"/> to <c>null</c> will treat
|
||||
/// the exception as handled, and it will not be rethrown by the runtime.
|
||||
///
|
||||
/// Setting <see cref="ExceptionHandled"/> to <c>true</c> will also mark the exception as handled.
|
||||
/// </remarks>
|
||||
public virtual ExceptionDispatchInfo ExceptionDispatchInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
return _exceptionDispatchInfo;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_exception = null;
|
||||
_exceptionDispatchInfo = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether or not the current <see cref="Exception"/> has been handled.
|
||||
///
|
||||
/// If <c>false</c> the <see cref="Exception"/> will be rethrown by the runtime after resource filters
|
||||
/// have executed.
|
||||
/// </summary>
|
||||
public virtual bool ExceptionHandled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the result.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <see cref="Result"/> may be provided by execution of the action itself or by another
|
||||
/// filter.
|
||||
///
|
||||
/// The <see cref="Result"/> has already been written to the response before being made available
|
||||
/// to resource filters.
|
||||
/// </remarks>
|
||||
public virtual IActionResult Result { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
// 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.ModelBinding;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// A context for resource filters. Allows modification of services and values used for
|
||||
/// model binding.
|
||||
/// </summary>
|
||||
public class ResourceExecutingContext : FilterContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ResourceExecutingContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="actionContext">The <see cref="ActionContext"/>.</param>
|
||||
/// <param name="filters">The list of <see cref="IFilter"/> instances.</param>
|
||||
public ResourceExecutingContext(ActionContext actionContext, IList<IFilter> filters)
|
||||
: base(actionContext, filters)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of <see cref="IInputFormatter"/> instances used by model binding.
|
||||
/// </summary>
|
||||
public virtual IList<IInputFormatter> InputFormatters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of <see cref="IModelBinder"/> instances used by model binding.
|
||||
/// </summary>
|
||||
public virtual IList<IModelBinder> ModelBinders { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the result of the action to be executed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Setting <see cref="Result"/> to a non-<c>null</c> value inside a resource filter will
|
||||
/// short-circuit execution of additional resource filtes and the action itself.
|
||||
/// </remarks>
|
||||
public virtual IActionResult Result { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of <see cref="IValueProviderFactory"/> instances used by model binding.
|
||||
/// </summary>
|
||||
public IList<IValueProviderFactory> ValueProviderFactories { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of <see cref="IModelValidatorProvider"/> instances used by model binding.
|
||||
/// </summary>
|
||||
public IList<IModelValidatorProvider> ValidatorProviders { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// 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.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// A delegate which asyncronously returns a <see cref="ResourceExecutedContext"/>.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="ResourceExecutedContext"/>.</returns>
|
||||
public delegate Task<ResourceExecutedContext> ResourceExecutionDelegate();
|
||||
}
|
||||
|
|
@ -1,14 +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
|
||||
{
|
||||
public class DefaultInputFormatterSelector : IInputFormatterSelector
|
||||
{
|
||||
public IInputFormatter SelectFormatter(InputFormatterContext context)
|
||||
|
||||
public IInputFormatter SelectFormatter(
|
||||
IReadOnlyList<IInputFormatter> inputFormatters,
|
||||
InputFormatterContext context)
|
||||
{
|
||||
var formatters = context.ActionContext.InputFormatters;
|
||||
foreach (var formatter in formatters)
|
||||
foreach (var formatter in inputFormatters)
|
||||
{
|
||||
if (formatter.CanRead(context))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
// 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
|
||||
{
|
||||
public interface IInputFormatterSelector
|
||||
{
|
||||
IInputFormatter SelectFormatter(InputFormatterContext context);
|
||||
IInputFormatter SelectFormatter(
|
||||
[NotNull] IReadOnlyList<IInputFormatter> inputFormatters,
|
||||
[NotNull] InputFormatterContext context);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// which can be used to invoke the action.
|
||||
/// </summary>
|
||||
/// <param name="context">The action context assoicated with the current action.</param>
|
||||
Task<IDictionary<string, object>> GetActionArgumentsAsync([NotNull] ActionContext context);
|
||||
/// <param name="bindingContext">The <see cref="ActionBindingContext"/>.</param>
|
||||
Task<IDictionary<string, object>> GetActionArgumentsAsync(
|
||||
[NotNull] ActionContext context,
|
||||
[NotNull] ActionBindingContext bindingContext);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// 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.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
|
|
@ -15,16 +16,19 @@ namespace Microsoft.AspNet.Mvc
|
|||
public class BodyModelBinder : MetadataAwareBinder<IFormatterBinderMetadata>
|
||||
{
|
||||
private readonly ActionContext _actionContext;
|
||||
private readonly IScopedInstance<ActionBindingContext> _bindingContext;
|
||||
private readonly IInputFormatterSelector _formatterSelector;
|
||||
private readonly IBodyModelValidator _bodyModelValidator;
|
||||
private readonly IValidationExcludeFiltersProvider _bodyValidationExcludeFiltersProvider;
|
||||
|
||||
public BodyModelBinder([NotNull] IScopedInstance<ActionContext> context,
|
||||
[NotNull] IScopedInstance<ActionBindingContext> bindingContext,
|
||||
[NotNull] IInputFormatterSelector selector,
|
||||
[NotNull] IBodyModelValidator bodyModelValidator,
|
||||
[NotNull] IValidationExcludeFiltersProvider bodyValidationExcludeFiltersProvider)
|
||||
{
|
||||
_actionContext = context.Value;
|
||||
_bindingContext = bindingContext;
|
||||
_formatterSelector = selector;
|
||||
_bodyModelValidator = bodyModelValidator;
|
||||
_bodyValidationExcludeFiltersProvider = bodyValidationExcludeFiltersProvider;
|
||||
|
|
@ -34,8 +38,10 @@ namespace Microsoft.AspNet.Mvc
|
|||
ModelBindingContext bindingContext,
|
||||
IFormatterBinderMetadata metadata)
|
||||
{
|
||||
var formatters = _bindingContext.Value.InputFormatters;
|
||||
|
||||
var formatterContext = new InputFormatterContext(_actionContext, bindingContext.ModelType);
|
||||
var formatter = _formatterSelector.SelectFormatter(formatterContext);
|
||||
var formatter = _formatterSelector.SelectFormatter(formatters.ToList(), formatterContext);
|
||||
|
||||
if (formatter == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,37 +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 System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class ActionBindingContext
|
||||
{
|
||||
public ActionBindingContext(ActionContext context,
|
||||
IModelMetadataProvider metadataProvider,
|
||||
IModelBinder modelBinder,
|
||||
IValueProvider valueProvider,
|
||||
IInputFormatterSelector inputFormatterSelector,
|
||||
IModelValidatorProvider validatorProvider)
|
||||
{
|
||||
ActionContext = context;
|
||||
MetadataProvider = metadataProvider;
|
||||
ModelBinder = modelBinder;
|
||||
ValueProvider = valueProvider;
|
||||
InputFormatterSelector = inputFormatterSelector;
|
||||
ValidatorProvider = validatorProvider;
|
||||
}
|
||||
public IModelBinder ModelBinder { get; set; }
|
||||
|
||||
public ActionContext ActionContext { get; private set; }
|
||||
public IValueProvider ValueProvider { get; set; }
|
||||
|
||||
public IModelMetadataProvider MetadataProvider { get; private set; }
|
||||
public IList<IInputFormatter> InputFormatters { get; set; }
|
||||
|
||||
public IModelBinder ModelBinder { get; private set; }
|
||||
|
||||
public IValueProvider ValueProvider { get; private set; }
|
||||
|
||||
public IInputFormatterSelector InputFormatterSelector { get; private set; }
|
||||
|
||||
public IModelValidatorProvider ValidatorProvider { get; private set; }
|
||||
public IModelValidatorProvider ValidatorProvider { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class DefaultActionBindingContextProvider : IActionBindingContextProvider
|
||||
{
|
||||
private readonly IModelMetadataProvider _modelMetadataProvider;
|
||||
private readonly ICompositeModelBinder _compositeModelBinder;
|
||||
private readonly IValueProviderFactory _compositeValueProviderFactory;
|
||||
private readonly IInputFormatterSelector _inputFormatterSelector;
|
||||
private readonly ICompositeModelValidatorProvider _validatorProvider;
|
||||
private Tuple<ActionContext, ActionBindingContext> _bindingContext;
|
||||
|
||||
public DefaultActionBindingContextProvider(IModelMetadataProvider modelMetadataProvider,
|
||||
ICompositeModelBinder compositeModelBinder,
|
||||
ICompositeValueProviderFactory compositeValueProviderFactory,
|
||||
IInputFormatterSelector inputFormatterProvider,
|
||||
ICompositeModelValidatorProvider validatorProvider)
|
||||
{
|
||||
_modelMetadataProvider = modelMetadataProvider;
|
||||
_compositeModelBinder = compositeModelBinder;
|
||||
_compositeValueProviderFactory = compositeValueProviderFactory;
|
||||
_inputFormatterSelector = inputFormatterProvider;
|
||||
_validatorProvider = validatorProvider;
|
||||
}
|
||||
|
||||
public Task<ActionBindingContext> GetActionBindingContextAsync(ActionContext actionContext)
|
||||
{
|
||||
if (_bindingContext != null)
|
||||
{
|
||||
if (actionContext == _bindingContext.Item1)
|
||||
{
|
||||
return Task.FromResult(_bindingContext.Item2);
|
||||
}
|
||||
}
|
||||
|
||||
var factoryContext = new ValueProviderFactoryContext(
|
||||
actionContext.HttpContext,
|
||||
actionContext.RouteData.Values);
|
||||
|
||||
var valueProvider = _compositeValueProviderFactory.GetValueProvider(factoryContext);
|
||||
|
||||
var context = new ActionBindingContext(
|
||||
actionContext,
|
||||
_modelMetadataProvider,
|
||||
_compositeModelBinder,
|
||||
valueProvider,
|
||||
_inputFormatterSelector,
|
||||
_validatorProvider);
|
||||
|
||||
_bindingContext = new Tuple<ActionContext, ActionBindingContext>(actionContext, context);
|
||||
|
||||
return Task.FromResult(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
// 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.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public interface IActionBindingContextProvider
|
||||
{
|
||||
Task<ActionBindingContext> GetActionBindingContextAsync(ActionContext actionContext);
|
||||
}
|
||||
}
|
||||
|
|
@ -1530,6 +1530,22 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
return GetString("SerializableError_DefaultError");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If an {0} provides a result value by setting the {1} property of {2} to a non-null value, then it cannot call the next filter by invoking {3}.
|
||||
/// </summary>
|
||||
internal static string AsyncResourceFilter_InvalidShortCircuit
|
||||
{
|
||||
get { return GetString("AsyncResourceFilter_InvalidShortCircuit"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If an {0} provides a result value by setting the {1} property of {2} to a non-null value, then it cannot call the next filter by invoking {3}.
|
||||
/// </summary>
|
||||
internal static string FormatAsyncResourceFilter_InvalidShortCircuit(object p0, object p1, object p2, object p3)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("AsyncResourceFilter_InvalidShortCircuit"), p0, p1, p2, p3);
|
||||
}
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ using System.Text;
|
|||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.Rendering.Expressions;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Rendering
|
||||
{
|
||||
|
|
@ -19,8 +20,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
{
|
||||
private const string HiddenListItem = @"<li style=""display:none""></li>";
|
||||
|
||||
private readonly IActionBindingContextProvider _actionBindingContextProvider;
|
||||
private readonly AntiForgery _antiForgery;
|
||||
private readonly IScopedInstance<ActionBindingContext> _bindingContextAccessor;
|
||||
private readonly IModelMetadataProvider _metadataProvider;
|
||||
private readonly IUrlHelper _urlHelper;
|
||||
|
||||
|
|
@ -28,13 +29,13 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
/// Initializes a new instance of the <see cref="DefaultHtmlGenerator"/> class.
|
||||
/// </summary>
|
||||
public DefaultHtmlGenerator(
|
||||
[NotNull] IActionBindingContextProvider actionBindingContextProvider,
|
||||
[NotNull] AntiForgery antiForgery,
|
||||
[NotNull] IScopedInstance<ActionBindingContext> bindingContextAccessor,
|
||||
[NotNull] IModelMetadataProvider metadataProvider,
|
||||
[NotNull] IUrlHelper urlHelper)
|
||||
{
|
||||
_actionBindingContextProvider = actionBindingContextProvider;
|
||||
_antiForgery = antiForgery;
|
||||
_bindingContextAccessor = bindingContextAccessor;
|
||||
_metadataProvider = metadataProvider;
|
||||
_urlHelper = urlHelper;
|
||||
|
||||
|
|
@ -723,12 +724,13 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
ModelMetadata metadata,
|
||||
string name)
|
||||
{
|
||||
var actionBindingContext = _actionBindingContextProvider.GetActionBindingContextAsync(viewContext).Result;
|
||||
var validatorProvider = _bindingContextAccessor.Value.ValidatorProvider;
|
||||
|
||||
metadata = metadata ??
|
||||
ExpressionMetadataProvider.FromStringExpression(name, viewContext.ViewData, _metadataProvider);
|
||||
|
||||
return actionBindingContext
|
||||
.ValidatorProvider
|
||||
return
|
||||
validatorProvider
|
||||
.GetValidators(metadata)
|
||||
.OfType<IClientModelValidator>()
|
||||
.SelectMany(v => v.GetClientValidationRules(
|
||||
|
|
|
|||
|
|
@ -412,4 +412,7 @@
|
|||
<data name="SerializableError_DefaultError" xml:space="preserve">
|
||||
<value>The input was not valid.</value>
|
||||
</data>
|
||||
<data name="AsyncResourceFilter_InvalidShortCircuit" xml:space="preserve">
|
||||
<value>If an {0} provides a result value by setting the {1} property of {2} to a non-null value, then it cannot call the next filter by invoking {3}.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -43,7 +43,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
var modelBinderProvider = instance as IModelBinderProvider;
|
||||
if (modelBinderProvider != null)
|
||||
{
|
||||
modelBinder = new CompositeModelBinder(modelBinderProvider);
|
||||
modelBinder = new CompositeModelBinder(modelBinderProvider.ModelBinders);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,30 +18,17 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
/// </remarks>
|
||||
public class CompositeModelBinder : ICompositeModelBinder
|
||||
{
|
||||
private readonly IModelBinderProvider _modelBindersProvider;
|
||||
private IReadOnlyList<IModelBinder> _binders;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the CompositeModelBinder class.
|
||||
/// </summary>
|
||||
/// <param name="modelBindersProvider">Provides a collection of <see cref="IModelBinder"/> instances.</param>
|
||||
public CompositeModelBinder(IModelBinderProvider modelBindersProvider)
|
||||
/// <param name="modelBinders">A collection of <see cref="IModelBinder"/> instances.</param>
|
||||
public CompositeModelBinder([NotNull] IEnumerable<IModelBinder> modelBinders)
|
||||
{
|
||||
_modelBindersProvider = modelBindersProvider;
|
||||
ModelBinders = new List<IModelBinder>(modelBinders);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<IModelBinder> ModelBinders
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_binders == null)
|
||||
{
|
||||
_binders = _modelBindersProvider.ModelBinders;
|
||||
}
|
||||
return _binders;
|
||||
}
|
||||
}
|
||||
public IReadOnlyList<IModelBinder> ModelBinders { get; }
|
||||
|
||||
public virtual async Task<bool> BindModelAsync([NotNull] ModelBindingContext bindingContext)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -14,14 +14,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="CompositeModelValidatorProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="provider">The <see cref="IModelValidatorProviderProvider"/> instance used to get the list of
|
||||
/// activated <see cref="IModelValidatorProvider"/> that this instance delegates to.</param>
|
||||
public CompositeModelValidatorProvider(IModelValidatorProviderProvider provider)
|
||||
/// <param name="providers">
|
||||
/// A collection of <see cref="IModelValidatorProvider"/> instances.
|
||||
/// </param>
|
||||
public CompositeModelValidatorProvider([NotNull] IEnumerable<IModelValidatorProvider> providers)
|
||||
{
|
||||
ValidatorProviders = provider.ModelValidatorProviders;
|
||||
ValidatorProviders = new List<IModelValidatorProvider>(providers);
|
||||
}
|
||||
|
||||
public IReadOnlyList<IModelValidatorProvider> ValidatorProviders { get; private set; }
|
||||
public IReadOnlyList<IModelValidatorProvider> ValidatorProviders { get; }
|
||||
|
||||
public IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,33 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="CompositeValueProvider"/> from the provided <paramref name="context"/>
|
||||
/// and <paramref name="factories"/>.
|
||||
/// </summary>
|
||||
/// <param name="factories">The set of <see cref="IValueProviderFactory"/> instances.</param>
|
||||
/// <param name="context">The <see cref="ValueProviderFactoryContext"/>.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="CompositeValueProvider"/> containing all <see cref="IValueProvider"/> instances
|
||||
/// created.
|
||||
/// </returns>
|
||||
public static CompositeValueProvider Create(
|
||||
[NotNull] IEnumerable<IValueProviderFactory> factories,
|
||||
[NotNull] ValueProviderFactoryContext context)
|
||||
{
|
||||
var composite = new CompositeValueProvider();
|
||||
foreach (var valueProvidersFactory in factories)
|
||||
{
|
||||
var valueProvider = valueProvidersFactory.GetValueProvider(context);
|
||||
if (valueProvider != null)
|
||||
{
|
||||
composite.Add(valueProvider);
|
||||
}
|
||||
}
|
||||
|
||||
return composite;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<bool> ContainsPrefixAsync(string prefix)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,6 +29,13 @@ namespace System.Web.Http
|
|||
[Activate]
|
||||
public ActionContext ActionContext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ActionBindingContext"/>.
|
||||
/// </summary>
|
||||
/// <remarks>The setter is intended for unit testing purposes only.</remarks>
|
||||
[Activate]
|
||||
public ActionBindingContext BindingContext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the http context.
|
||||
/// </summary>
|
||||
|
|
@ -40,6 +47,13 @@ namespace System.Web.Http
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IModelMetadataProvider"/>.
|
||||
/// </summary>
|
||||
/// <remarks>The setter is intended for unit testing purposes only.</remarks>
|
||||
[Activate]
|
||||
public IModelMetadataProvider MetadataProvider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets model state after the model binding process. This ModelState will be empty before model binding
|
||||
/// happens.
|
||||
|
|
@ -398,15 +412,15 @@ namespace System.Web.Http
|
|||
/// </param>
|
||||
public void Validate<TEntity>(TEntity entity, string keyPrefix)
|
||||
{
|
||||
var modelMetadata = MetadataProvider.GetMetadataForType(() => entity, typeof(TEntity));
|
||||
|
||||
var bodyValidationExcludeFiltersProvider = Context.RequestServices
|
||||
.GetRequiredService<IValidationExcludeFiltersProvider>();
|
||||
var validator = Context.RequestServices.GetRequiredService<IBodyModelValidator>();
|
||||
var metadataProvider = Context.RequestServices.GetRequiredService<IModelMetadataProvider>();
|
||||
var modelMetadata = metadataProvider.GetMetadataForType(() => entity, typeof(TEntity));
|
||||
var validatorProvider = Context.RequestServices.GetRequiredService<ICompositeModelValidatorProvider>();
|
||||
|
||||
var modelValidationContext = new ModelValidationContext(
|
||||
metadataProvider,
|
||||
validatorProvider,
|
||||
MetadataProvider,
|
||||
BindingContext.ValidatorProvider,
|
||||
ModelState,
|
||||
modelMetadata,
|
||||
containerMetadata: null,
|
||||
|
|
|
|||
|
|
@ -77,20 +77,16 @@ namespace Microsoft.AspNet.Mvc
|
|||
// Dataflow - ModelBinding, Validation and Formatting
|
||||
|
||||
yield return describe.Transient<IModelMetadataProvider, DataAnnotationsModelMetadataProvider>();
|
||||
yield return describe.Scoped<IActionBindingContextProvider, DefaultActionBindingContextProvider>();
|
||||
|
||||
yield return describe.Transient<IInputFormatterSelector, DefaultInputFormatterSelector>();
|
||||
yield return describe.Scoped<IInputFormattersProvider, DefaultInputFormattersProvider>();
|
||||
|
||||
yield return describe.Transient<IModelBinderProvider, DefaultModelBindersProvider>();
|
||||
yield return describe.Scoped<ICompositeModelBinder, CompositeModelBinder>();
|
||||
yield return describe.Transient<IValueProviderFactoryProvider, DefaultValueProviderFactoryProvider>();
|
||||
yield return describe.Scoped<ICompositeValueProviderFactory, CompositeValueProviderFactory>();
|
||||
yield return describe.Transient<IOutputFormattersProvider, DefaultOutputFormattersProvider>();
|
||||
yield return describe.Instance<JsonOutputFormatter>(new JsonOutputFormatter());
|
||||
|
||||
yield return describe.Transient<IModelValidatorProviderProvider, DefaultModelValidatorProviderProvider>();
|
||||
yield return describe.Scoped<ICompositeModelValidatorProvider, CompositeModelValidatorProvider>();
|
||||
yield return describe.Transient<IBodyModelValidator, DefaultBodyModelValidator>();
|
||||
yield return describe.Transient<IValidationExcludeFiltersProvider,
|
||||
DefaultValidationExcludeFiltersProvider>();
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
HttpContext = new DefaultHttpContext(),
|
||||
};
|
||||
|
||||
ModelBindingContext bindingContext = new ModelBindingContext
|
||||
var bindingContext = new ModelBindingContext
|
||||
{
|
||||
ModelMetadata = metadataProvider.GetMetadataForType(null, modelType),
|
||||
ModelName = "someName",
|
||||
|
|
@ -106,7 +106,11 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
var actionContext = CreateActionContext(new DefaultHttpContext());
|
||||
var inputFormatterSelector = new Mock<IInputFormatterSelector>();
|
||||
inputFormatterSelector.Setup(o => o.SelectFormatter(It.IsAny<InputFormatterContext>())).Returns(inputFormatter);
|
||||
inputFormatterSelector
|
||||
.Setup(o => o.SelectFormatter(
|
||||
It.IsAny<IReadOnlyList<IInputFormatter>>(),
|
||||
It.IsAny<InputFormatterContext>()))
|
||||
.Returns(inputFormatter);
|
||||
|
||||
if (validator == null)
|
||||
{
|
||||
|
|
@ -117,14 +121,27 @@ namespace Microsoft.AspNet.Mvc
|
|||
validator = mockValidator.Object;
|
||||
}
|
||||
|
||||
var bodyValidationPredicatesProvidwer = new Mock<IValidationExcludeFiltersProvider>();
|
||||
bodyValidationPredicatesProvidwer.SetupGet(o => o.ExcludeFilters)
|
||||
var bodyValidationPredicatesProvider = new Mock<IValidationExcludeFiltersProvider>();
|
||||
bodyValidationPredicatesProvider.SetupGet(o => o.ExcludeFilters)
|
||||
.Returns(new List<IExcludeTypeValidationFilter>());
|
||||
|
||||
var binder = new BodyModelBinder(actionContext,
|
||||
inputFormatterSelector.Object,
|
||||
validator,
|
||||
bodyValidationPredicatesProvidwer.Object);
|
||||
var bindingContext = new ActionBindingContext()
|
||||
{
|
||||
InputFormatters = new List<IInputFormatter>(),
|
||||
};
|
||||
|
||||
var bindingContextAccessor = new MockScopedInstance<ActionBindingContext>()
|
||||
{
|
||||
Value = bindingContext,
|
||||
};
|
||||
|
||||
var binder = new BodyModelBinder(
|
||||
actionContext,
|
||||
bindingContextAccessor,
|
||||
inputFormatterSelector.Object,
|
||||
validator,
|
||||
bodyValidationPredicatesProvider.Object);
|
||||
|
||||
return binder;
|
||||
}
|
||||
|
||||
|
|
@ -146,5 +163,10 @@ namespace Microsoft.AspNet.Mvc
|
|||
.Returns(actionContext);
|
||||
return contextAccessor.Object;
|
||||
}
|
||||
|
||||
private class Person
|
||||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -326,7 +326,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_ExceptionInAuthorizationFilterCannotBeHandledByExceptionFilters()
|
||||
public async Task InvokeAction_ExceptionInAuthorizationFilterCannotBeHandledByOtherFilters()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new InvalidCastException();
|
||||
|
|
@ -349,6 +349,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
// None of these filters should run
|
||||
var authorizationFilter2 = new Mock<IAuthorizationFilter>(MockBehavior.Strict);
|
||||
var resourceFilter = new Mock<IResourceFilter>(MockBehavior.Strict);
|
||||
var actionFilter = new Mock<IActionFilter>(MockBehavior.Strict);
|
||||
var resultFilter = new Mock<IResultFilter>(MockBehavior.Strict);
|
||||
|
||||
|
|
@ -357,6 +358,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
exceptionFilter.Object,
|
||||
authorizationFilter1.Object,
|
||||
authorizationFilter2.Object,
|
||||
resourceFilter.Object,
|
||||
actionFilter.Object,
|
||||
resultFilter.Object,
|
||||
});
|
||||
|
|
@ -1202,6 +1204,649 @@ namespace Microsoft.AspNet.Mvc
|
|||
resultFilter2.Verify(f => f.OnResultExecuting(It.IsAny<ResultExecutingContext>()), Times.Once());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesAsyncResourceFilter()
|
||||
{
|
||||
// Arrange
|
||||
var resourceFilter = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
await next();
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { resourceFilter.Object });
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
resourceFilter.Verify(
|
||||
f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesResourceFilter()
|
||||
{
|
||||
// Arrange
|
||||
var resourceFilter = new Mock<IResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecuting(It.IsAny<ResourceExecutingContext>()))
|
||||
.Verifiable();
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecuted(It.IsAny<ResourceExecutedContext>()))
|
||||
.Verifiable();
|
||||
|
||||
var invoker = CreateInvoker(resourceFilter.Object);
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
resourceFilter.Verify(
|
||||
f => f.OnResourceExecuted(It.IsAny<ResourceExecutedContext>()),
|
||||
Times.Once());
|
||||
resourceFilter.Verify(
|
||||
f => f.OnResourceExecuted(It.IsAny<ResourceExecutedContext>()),
|
||||
Times.Once());
|
||||
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesAsyncResourceFilter_WithActionResult_FromAction()
|
||||
{
|
||||
// Arrange
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var invoker = CreateInvoker(resourceFilter.Object);
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Same(_result, context.Result);
|
||||
|
||||
resourceFilter.Verify(
|
||||
f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesAsyncResourceFilter_WithActionResult_FromActionFilter()
|
||||
{
|
||||
// Arrange
|
||||
var expected = Mock.Of<IActionResult>();
|
||||
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var actionFilter = new Mock<IActionFilter>(MockBehavior.Strict);
|
||||
actionFilter
|
||||
.Setup(f => f.OnActionExecuting(It.IsAny<ActionExecutingContext>()))
|
||||
.Callback<ActionExecutingContext>((c) =>
|
||||
{
|
||||
c.Result = expected;
|
||||
});
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { resourceFilter.Object, actionFilter.Object });
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, context.Result);
|
||||
|
||||
resourceFilter.Verify(
|
||||
f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesAsyncResourceFilter_WithActionResult_FromExceptionFilter()
|
||||
{
|
||||
// Arrange
|
||||
var expected = Mock.Of<IActionResult>();
|
||||
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var exceptionFilter = new Mock<IExceptionFilter>(MockBehavior.Strict);
|
||||
exceptionFilter
|
||||
.Setup(f => f.OnException(It.IsAny<ExceptionContext>()))
|
||||
.Callback<ExceptionContext>((c) =>
|
||||
{
|
||||
c.Result = expected;
|
||||
});
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { resourceFilter.Object, exceptionFilter.Object }, actionThrows: true);
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, context.Result);
|
||||
Assert.Null(context.Exception);
|
||||
Assert.Null(context.ExceptionDispatchInfo);
|
||||
|
||||
resourceFilter.Verify(
|
||||
f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesAsyncResourceFilter_WithActionResult_FromResultFilter()
|
||||
{
|
||||
// Arrange
|
||||
var expected = Mock.Of<IActionResult>();
|
||||
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var resultFilter = new Mock<IResultFilter>(MockBehavior.Loose);
|
||||
resultFilter
|
||||
.Setup(f => f.OnResultExecuting(It.IsAny<ResultExecutingContext>()))
|
||||
.Callback<ResultExecutingContext>((c) =>
|
||||
{
|
||||
c.Result = expected;
|
||||
});
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { resourceFilter.Object, resultFilter.Object });
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, context.Result);
|
||||
|
||||
resourceFilter.Verify(
|
||||
f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesAsyncResourceFilter_HandleException_FromAction()
|
||||
{
|
||||
// Arrange
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
context.ExceptionHandled = true;
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { resourceFilter.Object }, actionThrows: true);
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Same(_actionException, context.Exception);
|
||||
Assert.Same(_actionException, context.ExceptionDispatchInfo.SourceException);
|
||||
|
||||
resourceFilter.Verify(
|
||||
f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesAsyncResourceFilter_HandleException_FromActionFilter()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new DataMisalignedException();
|
||||
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
context.ExceptionHandled = true;
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var actionFilter = new Mock<IActionFilter>(MockBehavior.Strict);
|
||||
actionFilter
|
||||
.Setup(f => f.OnActionExecuting(It.IsAny<ActionExecutingContext>()))
|
||||
.Callback<ActionExecutingContext>((c) =>
|
||||
{
|
||||
throw expected;
|
||||
});
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { resourceFilter.Object, actionFilter.Object });
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, context.Exception);
|
||||
Assert.Same(expected, context.ExceptionDispatchInfo.SourceException);
|
||||
|
||||
resourceFilter.Verify(
|
||||
f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesAsyncResourceFilter_HandlesException_FromExceptionFilter()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new DataMisalignedException();
|
||||
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
context.ExceptionHandled = true;
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var exceptionFilter = new Mock<IExceptionFilter>(MockBehavior.Strict);
|
||||
exceptionFilter
|
||||
.Setup(f => f.OnException(It.IsAny<ExceptionContext>()))
|
||||
.Callback<ExceptionContext>((c) =>
|
||||
{
|
||||
throw expected;
|
||||
});
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { resourceFilter.Object, exceptionFilter.Object }, actionThrows: true);
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, context.Exception);
|
||||
Assert.Same(expected, context.ExceptionDispatchInfo.SourceException);
|
||||
|
||||
resourceFilter.Verify(
|
||||
f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesAsyncResourceFilter_HandlesException_FromResultFilter()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new DataMisalignedException();
|
||||
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
context.ExceptionHandled = true;
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var resultFilter = new Mock<IResultFilter>(MockBehavior.Loose);
|
||||
resultFilter
|
||||
.Setup(f => f.OnResultExecuting(It.IsAny<ResultExecutingContext>()))
|
||||
.Callback<ResultExecutingContext>((c) =>
|
||||
{
|
||||
throw expected;
|
||||
});
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { resourceFilter.Object, resultFilter.Object });
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, context.Exception);
|
||||
Assert.Same(expected, context.ExceptionDispatchInfo.SourceException);
|
||||
|
||||
resourceFilter.Verify(
|
||||
f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesAsyncResourceFilter_HandleException_BySettingNull()
|
||||
{
|
||||
// Arrange
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
|
||||
Assert.Same(_actionException, context.Exception);
|
||||
Assert.Same(_actionException, context.ExceptionDispatchInfo.SourceException);
|
||||
|
||||
context.Exception = null;
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { resourceFilter.Object }, actionThrows: true);
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
resourceFilter.Verify(
|
||||
f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesAsyncResourceFilter_ThrowsUnhandledException()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new DataMisalignedException();
|
||||
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter1 = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter1
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var resourceFilter2 = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter2
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>((c, next) =>
|
||||
{
|
||||
throw expected;
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { resourceFilter1.Object, resourceFilter2.Object }, actionThrows: true);
|
||||
|
||||
// Act
|
||||
var exception = await Assert.ThrowsAsync<DataMisalignedException>(invoker.InvokeAsync);
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, exception);
|
||||
Assert.Same(expected, context.Exception);
|
||||
Assert.Same(expected, context.ExceptionDispatchInfo.SourceException);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesResourceFilter_OnResourceExecuting_ThrowsUnhandledException()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new DataMisalignedException();
|
||||
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter1 = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter1
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var resourceFilter2 = new Mock<IResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter2
|
||||
.Setup(f => f.OnResourceExecuting(It.IsAny<ResourceExecutingContext>()))
|
||||
.Callback<ResourceExecutingContext>((c) =>
|
||||
{
|
||||
throw expected;
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { resourceFilter1.Object, resourceFilter2.Object }, actionThrows: true);
|
||||
|
||||
// Act
|
||||
var exception = await Assert.ThrowsAsync<DataMisalignedException>(invoker.InvokeAsync);
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, exception);
|
||||
Assert.Same(expected, context.Exception);
|
||||
Assert.Same(expected, context.ExceptionDispatchInfo.SourceException);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesResourceFilter_OnResourceExecuted_ThrowsUnhandledException()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new DataMisalignedException();
|
||||
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter1 = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter1
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var resourceFilter2 = new Mock<IResourceFilter>(MockBehavior.Loose);
|
||||
resourceFilter2
|
||||
.Setup(f => f.OnResourceExecuted(It.IsAny<ResourceExecutedContext>()))
|
||||
.Callback<ResourceExecutedContext>((c) =>
|
||||
{
|
||||
throw expected;
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { resourceFilter1.Object, resourceFilter2.Object }, actionThrows: true);
|
||||
|
||||
// Act
|
||||
var exception = await Assert.ThrowsAsync<DataMisalignedException>(invoker.InvokeAsync);
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, exception);
|
||||
Assert.Same(expected, context.Exception);
|
||||
Assert.Same(expected, context.ExceptionDispatchInfo.SourceException);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesAsyncResourceFilter_ShortCircuit()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new Mock<IActionResult>(MockBehavior.Strict);
|
||||
expected
|
||||
.Setup(r => r.ExecuteResultAsync(It.IsAny<ActionContext>()))
|
||||
.Returns(Task.FromResult(true))
|
||||
.Verifiable();
|
||||
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter1 = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter1
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var resourceFilter2 = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter2
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>((c, next) =>
|
||||
{
|
||||
c.Result = expected.Object;
|
||||
return Task.FromResult(true);
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var resourceFilter3 = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
var exceptionFilter = new Mock<IExceptionFilter>(MockBehavior.Strict);
|
||||
var actionFilter = new Mock<IAsyncActionFilter>(MockBehavior.Strict);
|
||||
var resultFilter = new Mock<IAsyncResultFilter>(MockBehavior.Strict);
|
||||
|
||||
var invoker = CreateInvoker(
|
||||
new IFilter[]
|
||||
{
|
||||
resourceFilter1.Object, // This filter should see the result retured from resourceFilter2
|
||||
resourceFilter2.Object, // This filter will short circuit
|
||||
resourceFilter3.Object, // This shouldn't run - it will throw if it does
|
||||
exceptionFilter.Object, // This shouldn't run - it will throw if it does
|
||||
actionFilter.Object, // This shouldn't run - it will throw if it does
|
||||
resultFilter.Object // This shouldn't run - it will throw if it does
|
||||
},
|
||||
// The action won't run
|
||||
actionThrows: true);
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected.Object, context.Result);
|
||||
Assert.True(context.Canceled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesResourceFilter_ShortCircuit()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new Mock<IActionResult>(MockBehavior.Strict);
|
||||
expected
|
||||
.Setup(r => r.ExecuteResultAsync(It.IsAny<ActionContext>()))
|
||||
.Returns(Task.FromResult(true))
|
||||
.Verifiable();
|
||||
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter1 = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter1
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
context = await next();
|
||||
});
|
||||
|
||||
var resourceFilter2 = new Mock<IResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter2
|
||||
.Setup(f => f.OnResourceExecuting(It.IsAny<ResourceExecutingContext>()))
|
||||
.Callback<ResourceExecutingContext>((c) =>
|
||||
{
|
||||
c.Result = expected.Object;
|
||||
});
|
||||
|
||||
var resourceFilter3 = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
var actionFilter = new Mock<IAsyncActionFilter>(MockBehavior.Strict);
|
||||
var resultFilter = new Mock<IAsyncResultFilter>(MockBehavior.Strict);
|
||||
|
||||
var invoker = CreateInvoker(
|
||||
new IFilter[]
|
||||
{
|
||||
resourceFilter1.Object, // This filter should see the result retured from resourceFilter2
|
||||
resourceFilter2.Object,
|
||||
resourceFilter3.Object, // This shouldn't run - it will throw if it does
|
||||
actionFilter.Object, // This shouldn't run - it will throw if it does
|
||||
resultFilter.Object // This shouldn't run - it will throw if it does
|
||||
},
|
||||
// The action won't run
|
||||
actionThrows: true);
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected.Object, context.Result);
|
||||
Assert.True(context.Canceled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_InvokesAsyncResourceFilter_InvalidShortCircuit()
|
||||
{
|
||||
// Arrange
|
||||
var message =
|
||||
"If an IAsyncResourceFilter provides a result value by setting the Result property of " +
|
||||
"ResourceExecutingContext to a non-null value, then it cannot call the next filter by invoking " +
|
||||
"ResourceExecutionDelegate.";
|
||||
|
||||
ResourceExecutedContext context = null;
|
||||
var resourceFilter = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
// This is not valid.
|
||||
c.Result = Mock.Of<IActionResult>();
|
||||
context = await next();
|
||||
});
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { resourceFilter.Object, });
|
||||
|
||||
// Act
|
||||
var exception = await Assert.ThrowsAsync<InvalidOperationException>(invoker.InvokeAsync);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(message, exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAction_AuthorizationFilter_ChallengePreventsResourceFiltersFromRunning()
|
||||
{
|
||||
// Arrange
|
||||
var resourceFilter = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
|
||||
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
|
||||
{
|
||||
await next();
|
||||
})
|
||||
.Verifiable();
|
||||
|
||||
var authorizationFilter = new Mock<IAuthorizationFilter>(MockBehavior.Strict);
|
||||
authorizationFilter
|
||||
.Setup(f => f.OnAuthorization(It.IsAny<AuthorizationContext>()))
|
||||
.Callback<AuthorizationContext>((c) =>
|
||||
{
|
||||
c.Result = _result;
|
||||
});
|
||||
|
||||
var invoker = CreateInvoker(new IFilter[] { authorizationFilter.Object, resourceFilter.Object, });
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
resourceFilter.Verify(
|
||||
f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()),
|
||||
Times.Never());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateActionResult_ReturnsSameActionResult()
|
||||
{
|
||||
|
|
@ -1320,11 +1965,6 @@ namespace Microsoft.AspNet.Mvc
|
|||
controllerFactory.Setup(c => c.CreateController(It.IsAny<ActionContext>())).Returns(this);
|
||||
controllerFactory.Setup(m => m.ReleaseController(this)).Verifiable();
|
||||
|
||||
var actionBindingContextProvider = new Mock<IActionBindingContextProvider>(MockBehavior.Strict);
|
||||
actionBindingContextProvider
|
||||
.Setup(abcp => abcp.GetActionBindingContextAsync(It.IsAny<ActionContext>()))
|
||||
.Returns(Task.FromResult(new ActionBindingContext(null, null, null, null, null, null)));
|
||||
|
||||
var filterProvider = new Mock<INestedProviderManager<FilterProviderContext>>(MockBehavior.Strict);
|
||||
filterProvider
|
||||
.Setup(fp => fp.Invoke(It.IsAny<FilterProviderContext>()))
|
||||
|
|
@ -1339,8 +1979,14 @@ namespace Microsoft.AspNet.Mvc
|
|||
filterProvider.Object,
|
||||
controllerFactory,
|
||||
actionDescriptor,
|
||||
new EmptyModelMetadataProvider(),
|
||||
inputFormattersProvider.Object,
|
||||
Mock.Of<IControllerActionArgumentBinder>());
|
||||
new DefaultInputFormatterSelector(),
|
||||
Mock.Of<IControllerActionArgumentBinder>(),
|
||||
new MockModelBinderProvider(),
|
||||
new MockModelValidatorProviderProvider(),
|
||||
new MockValueProviderFactoryProvider(),
|
||||
new MockScopedInstance<ActionBindingContext>());
|
||||
|
||||
return invoker;
|
||||
}
|
||||
|
|
@ -1354,8 +2000,9 @@ namespace Microsoft.AspNet.Mvc
|
|||
var actionDescriptor = new ControllerActionDescriptor
|
||||
{
|
||||
MethodInfo = typeof(TestController).GetTypeInfo()
|
||||
.DeclaredMethods
|
||||
.First(m => m.Name.Equals("ActionMethodWithDefaultValues", StringComparison.Ordinal)),
|
||||
.DeclaredMethods
|
||||
.First(m => m.Name.Equals("ActionMethodWithDefaultValues", StringComparison.Ordinal)),
|
||||
|
||||
Parameters = new List<ParameterDescriptor>
|
||||
{
|
||||
new ParameterDescriptor
|
||||
|
|
@ -1375,31 +2022,29 @@ namespace Microsoft.AspNet.Mvc
|
|||
context.SetupGet(c => c.Items)
|
||||
.Returns(new Dictionary<object, object>());
|
||||
var routeContext = new RouteContext(context.Object);
|
||||
var actionContext = new ActionContext(routeContext,
|
||||
actionDescriptor);
|
||||
var bindingContext = new ActionBindingContext(actionContext,
|
||||
Mock.Of<IModelMetadataProvider>(),
|
||||
binder.Object,
|
||||
Mock.Of<IValueProvider>(),
|
||||
Mock.Of<IInputFormatterSelector>(),
|
||||
Mock.Of<IModelValidatorProvider>());
|
||||
|
||||
var actionBindingContextProvider = new Mock<IActionBindingContextProvider>();
|
||||
actionBindingContextProvider.Setup(p => p.GetActionBindingContextAsync(It.IsAny<ActionContext>()))
|
||||
.Returns(Task.FromResult(bindingContext));
|
||||
var actionContext = new ActionContext(routeContext, actionDescriptor);
|
||||
|
||||
var controllerFactory = new Mock<IControllerFactory>();
|
||||
controllerFactory.Setup(c => c.CreateController(It.IsAny<ActionContext>()))
|
||||
.Returns(new TestController());
|
||||
var inputFormattersProvider = new Mock<IInputFormattersProvider>();
|
||||
inputFormattersProvider.SetupGet(o => o.InputFormatters)
|
||||
.Returns(new List<IInputFormatter>());
|
||||
var invoker = new ControllerActionInvoker(actionContext,
|
||||
Mock.Of<INestedProviderManager<FilterProviderContext>>(),
|
||||
controllerFactory.Object,
|
||||
actionDescriptor,
|
||||
inputFormattersProvider.Object,
|
||||
new DefaultControllerActionArgumentBinder(
|
||||
actionBindingContextProvider.Object));
|
||||
|
||||
var invoker = new ControllerActionInvoker(
|
||||
actionContext,
|
||||
Mock.Of<INestedProviderManager<FilterProviderContext>>(),
|
||||
controllerFactory.Object,
|
||||
actionDescriptor,
|
||||
metadataProvider,
|
||||
inputFormattersProvider.Object,
|
||||
new DefaultInputFormatterSelector(),
|
||||
new DefaultControllerActionArgumentBinder(metadataProvider),
|
||||
new MockModelBinderProvider() { ModelBinders = new List<IModelBinder>() { binder.Object } },
|
||||
new MockModelValidatorProviderProvider(),
|
||||
new MockValueProviderFactoryProvider(),
|
||||
new MockScopedInstance<ActionBindingContext>());
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
|
@ -1458,14 +2103,27 @@ namespace Microsoft.AspNet.Mvc
|
|||
INestedProviderManager<FilterProviderContext> filterProvider,
|
||||
Mock<IControllerFactory> controllerFactoryMock,
|
||||
ControllerActionDescriptor descriptor,
|
||||
IModelMetadataProvider modelMetadataProvider,
|
||||
IInputFormattersProvider inputFormattersProvider,
|
||||
IControllerActionArgumentBinder controllerActionArgumentBinder) :
|
||||
base(actionContext,
|
||||
filterProvider,
|
||||
controllerFactoryMock.Object,
|
||||
descriptor,
|
||||
inputFormattersProvider,
|
||||
controllerActionArgumentBinder)
|
||||
IInputFormatterSelector inputFormatterSelector,
|
||||
IControllerActionArgumentBinder controllerActionArgumentBinder,
|
||||
IModelBinderProvider modelBinderProvider,
|
||||
IModelValidatorProviderProvider modelValidatorProviderProvider,
|
||||
IValueProviderFactoryProvider valueProviderFactoryProvider,
|
||||
IScopedInstance<ActionBindingContext> actionBindingContext)
|
||||
: base(
|
||||
actionContext,
|
||||
filterProvider,
|
||||
controllerFactoryMock.Object,
|
||||
descriptor,
|
||||
modelMetadataProvider,
|
||||
inputFormattersProvider,
|
||||
inputFormatterSelector,
|
||||
controllerActionArgumentBinder,
|
||||
modelBinderProvider,
|
||||
modelValidatorProviderProvider,
|
||||
valueProviderFactoryProvider,
|
||||
actionBindingContext)
|
||||
{
|
||||
_factoryMock = controllerFactoryMock;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1301,21 +1301,20 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
{
|
||||
var metadataProvider = new DataAnnotationsModelMetadataProvider();
|
||||
var actionContext = new ActionContext(Mock.Of<HttpContext>(), new RouteData(), new ActionDescriptor());
|
||||
var bindingContext = new ActionBindingContext(actionContext,
|
||||
metadataProvider,
|
||||
binder,
|
||||
provider ?? Mock.Of<IValueProvider>(),
|
||||
Mock.Of<IInputFormatterSelector>(),
|
||||
Mock.Of<IModelValidatorProvider>());
|
||||
var bindingContextProvider = new Mock<IActionBindingContextProvider>();
|
||||
bindingContextProvider.Setup(b => b.GetActionBindingContextAsync(actionContext))
|
||||
.Returns(Task.FromResult(bindingContext));
|
||||
|
||||
var viewData = new ViewDataDictionary(metadataProvider, new ModelStateDictionary());
|
||||
return new Controller
|
||||
|
||||
var bindingContext = new ActionBindingContext()
|
||||
{
|
||||
ModelBinder = binder,
|
||||
ValueProvider = provider,
|
||||
};
|
||||
|
||||
return new Controller()
|
||||
{
|
||||
ActionContext = actionContext,
|
||||
BindingContextProvider = bindingContextProvider.Object,
|
||||
BindingContext = bindingContext,
|
||||
MetadataProvider = metadataProvider,
|
||||
ViewData = viewData
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||
using Microsoft.Framework.Runtime;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using Microsoft.AspNet.Http;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Core
|
||||
{
|
||||
|
|
@ -32,6 +33,8 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
|
||||
// Assert
|
||||
Assert.Equal(new[] { "SomeRandomAssembly" }, candidates.Select(a => a.Name));
|
||||
|
||||
var context = new Mock<HttpContext>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using Microsoft.AspNet.Http;
|
|||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -18,18 +19,14 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
public void Activate_SetsPropertiesFromActionContextHierarchy()
|
||||
{
|
||||
// Arrange
|
||||
var services = new Mock<IServiceProvider>();
|
||||
services.Setup(s => s.GetService(typeof(IUrlHelper)))
|
||||
.Returns(Mock.Of<IUrlHelper>());
|
||||
services.Setup(s => s.GetService(typeof(IModelMetadataProvider)))
|
||||
.Returns(new EmptyModelMetadataProvider());
|
||||
var services = GetServices();
|
||||
|
||||
var httpRequest = Mock.Of<HttpRequest>();
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.SetupGet(c => c.Request)
|
||||
.Returns(httpRequest);
|
||||
httpContext.SetupGet(c => c.RequestServices)
|
||||
.Returns(services.Object);
|
||||
.Returns(services);
|
||||
var routeContext = new RouteContext(httpContext.Object);
|
||||
var controller = new TestController();
|
||||
var context = new ActionContext(routeContext, new ActionDescriptor())
|
||||
|
|
@ -51,17 +48,11 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
public void Activate_SetsViewDatDictionary()
|
||||
{
|
||||
// Arrange
|
||||
var services = new Mock<IServiceProvider>();
|
||||
services.Setup(s => s.GetService(typeof(IModelMetadataProvider)))
|
||||
.Returns(new EmptyModelMetadataProvider());
|
||||
services.Setup(s => s.GetService(typeof(ICompositeViewEngine)))
|
||||
.Returns(Mock.Of<ICompositeViewEngine>());
|
||||
services.Setup(s => s.GetService(typeof(IUrlHelper)))
|
||||
.Returns(Mock.Of<IUrlHelper>());
|
||||
var services = GetServices();
|
||||
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.SetupGet(c => c.RequestServices)
|
||||
.Returns(services.Object);
|
||||
.Returns(services);
|
||||
var routeContext = new RouteContext(httpContext.Object);
|
||||
var controller = new TestController();
|
||||
var context = new ActionContext(routeContext, new ActionDescriptor())
|
||||
|
|
@ -78,19 +69,44 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Activate_PopulatesServicesFromServiceContainer()
|
||||
public void Activate_SetsBindingContext()
|
||||
{
|
||||
// Arrange
|
||||
var urlHelper = Mock.Of<IUrlHelper>();
|
||||
var services = new Mock<IServiceProvider>();
|
||||
services.Setup(s => s.GetService(typeof(IUrlHelper)))
|
||||
.Returns(urlHelper);
|
||||
services.Setup(s => s.GetService(typeof(IModelMetadataProvider)))
|
||||
.Returns(new EmptyModelMetadataProvider());
|
||||
var bindingContext = new ActionBindingContext();
|
||||
|
||||
var services = GetServices();
|
||||
services.GetRequiredService<IScopedInstance<ActionBindingContext>>().Value = bindingContext;
|
||||
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.SetupGet(c => c.RequestServices)
|
||||
.Returns(services.Object);
|
||||
.Returns(services);
|
||||
var routeContext = new RouteContext(httpContext.Object);
|
||||
|
||||
var controller = new TestController();
|
||||
var context = new ActionContext(routeContext, new ActionDescriptor())
|
||||
{
|
||||
Controller = controller
|
||||
};
|
||||
|
||||
var activator = new DefaultControllerActivator();
|
||||
|
||||
// Act
|
||||
activator.Activate(controller, context);
|
||||
|
||||
// Assert
|
||||
Assert.Same(bindingContext, controller.BindingContext);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Activate_PopulatesServicesFromServiceContainer()
|
||||
{
|
||||
// Arrange
|
||||
var services = GetServices();
|
||||
var urlHelper = services.GetRequiredService<IUrlHelper>();
|
||||
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.SetupGet(c => c.RequestServices)
|
||||
.Returns(services);
|
||||
var routeContext = new RouteContext(httpContext.Object);
|
||||
var controller = new TestController();
|
||||
var context = new ActionContext(routeContext, new ActionDescriptor())
|
||||
|
|
@ -110,17 +126,13 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
public void Activate_IgnoresPropertiesThatAreNotDecoratedWithActivateAttribute()
|
||||
{
|
||||
// Arrange
|
||||
var services = new Mock<IServiceProvider>();
|
||||
services.Setup(s => s.GetService(typeof(IUrlHelper)))
|
||||
.Returns(Mock.Of<IUrlHelper>());
|
||||
services.Setup(s => s.GetService(typeof(IModelMetadataProvider)))
|
||||
.Returns(new EmptyModelMetadataProvider());
|
||||
var services = GetServices();
|
||||
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.SetupGet(c => c.Response)
|
||||
.Returns(Mock.Of<HttpResponse>());
|
||||
httpContext.SetupGet(c => c.RequestServices)
|
||||
.Returns(services.Object);
|
||||
.Returns(services);
|
||||
var routeContext = new RouteContext(httpContext.Object);
|
||||
var controller = new TestController();
|
||||
var context = new ActionContext(routeContext, new ActionDescriptor())
|
||||
|
|
@ -136,11 +148,27 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
Assert.Null(controller.Response);
|
||||
}
|
||||
|
||||
private IServiceProvider GetServices()
|
||||
{
|
||||
var services = new Mock<IServiceProvider>();
|
||||
services.Setup(s => s.GetService(typeof(IUrlHelper)))
|
||||
.Returns(Mock.Of<IUrlHelper>());
|
||||
services.Setup(s => s.GetService(typeof(IModelMetadataProvider)))
|
||||
.Returns(new EmptyModelMetadataProvider());
|
||||
services
|
||||
.Setup(s => s.GetService(typeof(IScopedInstance<ActionBindingContext>)))
|
||||
.Returns(new MockScopedInstance<ActionBindingContext>());
|
||||
return services.Object;
|
||||
}
|
||||
|
||||
public class TestController
|
||||
{
|
||||
[Activate]
|
||||
public ActionContext ActionContext { get; set; }
|
||||
|
||||
[Activate]
|
||||
public ActionBindingContext BindingContext { get; set; }
|
||||
|
||||
[Activate]
|
||||
public HttpContext HttpContext { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -17,19 +17,19 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
{
|
||||
// Arrange
|
||||
var actionContext = GetActionContext();
|
||||
var context = new InputFormatterContext(actionContext, typeof(int));
|
||||
actionContext.InputFormatters = new List<IInputFormatter>()
|
||||
{
|
||||
new TestInputFormatter(false, 0),
|
||||
new TestInputFormatter(false, 1),
|
||||
new TestInputFormatter(true, 2),
|
||||
new TestInputFormatter(true, 3)
|
||||
};
|
||||
var inputFormatters = new List<IInputFormatter>()
|
||||
{
|
||||
new TestInputFormatter(false, 0),
|
||||
new TestInputFormatter(false, 1),
|
||||
new TestInputFormatter(true, 2),
|
||||
new TestInputFormatter(true, 3)
|
||||
};
|
||||
|
||||
var context = new InputFormatterContext(actionContext, typeof(int));
|
||||
var selector = new DefaultInputFormatterSelector();
|
||||
|
||||
// Act
|
||||
var selectedFormatter = selector.SelectFormatter(context);
|
||||
var selectedFormatter = selector.SelectFormatter(inputFormatters, context);
|
||||
|
||||
// Assert
|
||||
var testFormatter = Assert.IsType<TestInputFormatter>(selectedFormatter);
|
||||
|
|
@ -38,8 +38,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
|
||||
private static ActionContext GetActionContext()
|
||||
{
|
||||
var httpContext = Mock.Of<HttpContext>();
|
||||
return new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
||||
return new ActionContext(Mock.Of<HttpContext>(), new RouteData(), new ActionDescriptor());
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,119 +0,0 @@
|
|||
// 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.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.OptionDescriptors;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class InputObjectBindingTests
|
||||
{
|
||||
private static ControllerActionInvoker GetControllerActionInvoker(
|
||||
string input, Type parameterType, IInputFormatter selectedFormatter, string contentType)
|
||||
{
|
||||
var mvcOptions = new MvcOptions();
|
||||
var setup = new MvcOptionsSetup();
|
||||
|
||||
setup.Configure(mvcOptions);
|
||||
var accessor = new Mock<IOptions<MvcOptions>>();
|
||||
accessor.SetupGet(a => a.Options)
|
||||
.Returns(mvcOptions);
|
||||
var validatorProvider = new DefaultModelValidatorProviderProvider(
|
||||
accessor.Object, Mock.Of<ITypeActivator>(), Mock.Of<IServiceProvider>());
|
||||
|
||||
Func<object, int> method = x => 1;
|
||||
var actionDescriptor = new ControllerActionDescriptor
|
||||
{
|
||||
MethodInfo = method.Method,
|
||||
Parameters = new List<ParameterDescriptor>
|
||||
{
|
||||
new ParameterDescriptor
|
||||
{
|
||||
BinderMetadata = new FromBodyAttribute(),
|
||||
Name = "foo",
|
||||
ParameterType = parameterType,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var metadataProvider = new EmptyModelMetadataProvider();
|
||||
var actionContext = GetActionContext(
|
||||
Encodings.UTF8EncodingWithoutBOM.GetBytes(input), actionDescriptor, contentType);
|
||||
|
||||
var inputFormatterSelector = new Mock<IInputFormatterSelector>();
|
||||
inputFormatterSelector.Setup(a => a.SelectFormatter(It.IsAny<InputFormatterContext>()))
|
||||
.Returns(selectedFormatter);
|
||||
var bindingContext = new ActionBindingContext(actionContext,
|
||||
metadataProvider,
|
||||
Mock.Of<IModelBinder>(),
|
||||
Mock.Of<IValueProvider>(),
|
||||
inputFormatterSelector.Object,
|
||||
new CompositeModelValidatorProvider(validatorProvider));
|
||||
|
||||
var actionBindingContextProvider = new Mock<IActionBindingContextProvider>();
|
||||
actionBindingContextProvider.Setup(p => p.GetActionBindingContextAsync(It.IsAny<ActionContext>()))
|
||||
.Returns(Task.FromResult(bindingContext));
|
||||
|
||||
var inputFormattersProvider = new Mock<IInputFormattersProvider>();
|
||||
inputFormattersProvider.SetupGet(o => o.InputFormatters)
|
||||
.Returns(new List<IInputFormatter>());
|
||||
return new ControllerActionInvoker(actionContext,
|
||||
Mock.Of<INestedProviderManager<FilterProviderContext>>(),
|
||||
Mock.Of<IControllerFactory>(),
|
||||
actionDescriptor,
|
||||
inputFormattersProvider.Object,
|
||||
Mock.Of<IControllerActionArgumentBinder>());
|
||||
}
|
||||
|
||||
private static ActionContext GetActionContext(byte[] contentBytes,
|
||||
ActionDescriptor actionDescriptor,
|
||||
string contentType)
|
||||
{
|
||||
return new ActionContext(GetHttpContext(contentBytes, contentType),
|
||||
new RouteData(),
|
||||
actionDescriptor);
|
||||
}
|
||||
|
||||
private static HttpContext GetHttpContext(byte[] contentBytes,
|
||||
string contentType)
|
||||
{
|
||||
var request = new Mock<HttpRequest>();
|
||||
var headers = new Mock<IHeaderDictionary>();
|
||||
request.SetupGet(r => r.Headers).Returns(headers.Object);
|
||||
request.SetupGet(f => f.Body).Returns(new MemoryStream(contentBytes));
|
||||
request.SetupGet(f => f.ContentType).Returns(contentType);
|
||||
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.SetupGet(c => c.Request).Returns(request.Object);
|
||||
httpContext.SetupGet(c => c.Request).Returns(request.Object);
|
||||
return httpContext.Object;
|
||||
}
|
||||
}
|
||||
|
||||
public class Person
|
||||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
public class User : Person
|
||||
{
|
||||
[MinLength(5)]
|
||||
public string UserName { get; set; }
|
||||
}
|
||||
|
||||
public class Customers
|
||||
{
|
||||
[Required]
|
||||
public List<User> Users { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// 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.ModelBinding
|
||||
{
|
||||
public class MockModelBinderProvider : IModelBinderProvider
|
||||
{
|
||||
public List<IModelBinder> ModelBinders { get; set; } = new List<IModelBinder>();
|
||||
|
||||
IReadOnlyList<IModelBinder> IModelBinderProvider.ModelBinders { get { return ModelBinders; } }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// 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.ModelBinding
|
||||
{
|
||||
public class MockModelValidatorProviderProvider: IModelValidatorProviderProvider
|
||||
{
|
||||
public List<IModelValidatorProvider> ModelValidatorProviders { get; } = new List<IModelValidatorProvider>();
|
||||
|
||||
IReadOnlyList<IModelValidatorProvider> IModelValidatorProviderProvider.ModelValidatorProviders
|
||||
{
|
||||
get { return ModelValidatorProviders; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// 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.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class MockScopedInstance<T> : IScopedInstance<T>
|
||||
{
|
||||
public T Value { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// 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.ModelBinding
|
||||
{
|
||||
public class MockValueProviderFactoryProvider : IValueProviderFactoryProvider
|
||||
{
|
||||
public List<IValueProviderFactory> ValueProviderFactories { get; } = new List<IValueProviderFactory>();
|
||||
|
||||
IReadOnlyList<IValueProviderFactory> IValueProviderFactoryProvider.ValueProviderFactories
|
||||
{
|
||||
get { return ValueProviderFactories; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -52,22 +52,21 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
public void GetModelBindingContext_ReturnsOnlyIncludedProperties_UsingBindAttributeInclude()
|
||||
{
|
||||
// Arrange
|
||||
var actionContext = new ActionContext(new RouteContext(Mock.Of<HttpContext>()),
|
||||
Mock.Of<ActionDescriptor>());
|
||||
var actionContext = new ActionContext(
|
||||
new RouteContext(Mock.Of<HttpContext>()),
|
||||
Mock.Of<ActionDescriptor>());
|
||||
|
||||
var metadataProvider = new DataAnnotationsModelMetadataProvider();
|
||||
var modelMetadata = metadataProvider.GetMetadataForType(
|
||||
modelAccessor: null, modelType: typeof(TypeWithIncludedPropertiesUsingBindAttribute));
|
||||
|
||||
var actionBindingContext = new ActionBindingContext(actionContext,
|
||||
Mock.Of<IModelMetadataProvider>(),
|
||||
Mock.Of<IModelBinder>(),
|
||||
Mock.Of<IValueProvider>(),
|
||||
Mock.Of<IInputFormatterSelector>(),
|
||||
Mock.Of<IModelValidatorProvider>());
|
||||
var actionBindingContext = new ActionBindingContext();
|
||||
|
||||
// Act
|
||||
var context = DefaultControllerActionArgumentBinder.GetModelBindingContext(
|
||||
modelMetadata, actionBindingContext, Mock.Of<OperationBindingContext>());
|
||||
modelMetadata,
|
||||
actionContext,
|
||||
Mock.Of<OperationBindingContext>());
|
||||
|
||||
// Assert
|
||||
Assert.True(context.PropertyFilter(context, "IncludedExplicitly1"));
|
||||
|
|
@ -80,23 +79,21 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
// Arrange
|
||||
var type = typeof(ControllerActionArgumentBinderTests);
|
||||
var methodInfo = type.GetMethod("ParameterWithNoBindAttribute");
|
||||
var actionContext = new ActionContext(new RouteContext(Mock.Of<HttpContext>()),
|
||||
Mock.Of<ActionDescriptor>());
|
||||
|
||||
var actionContext = new ActionContext(
|
||||
new RouteContext(Mock.Of<HttpContext>()),
|
||||
Mock.Of<ActionDescriptor>());
|
||||
|
||||
var metadataProvider = new DataAnnotationsModelMetadataProvider();
|
||||
var modelMetadata = metadataProvider.GetMetadataForParameter(modelAccessor: null,
|
||||
methodInfo: methodInfo,
|
||||
parameterName: "parameter");
|
||||
|
||||
var actionBindingContext = new ActionBindingContext(actionContext,
|
||||
Mock.Of<IModelMetadataProvider>(),
|
||||
Mock.Of<IModelBinder>(),
|
||||
Mock.Of<IValueProvider>(),
|
||||
Mock.Of<IInputFormatterSelector>(),
|
||||
Mock.Of<IModelValidatorProvider>());
|
||||
// Act
|
||||
var context = DefaultControllerActionArgumentBinder.GetModelBindingContext(
|
||||
modelMetadata, actionBindingContext, Mock.Of<OperationBindingContext>());
|
||||
modelMetadata,
|
||||
actionContext,
|
||||
Mock.Of<OperationBindingContext>());
|
||||
|
||||
// Assert
|
||||
Assert.Equal("TypePrefix", context.ModelName);
|
||||
|
|
@ -113,24 +110,21 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
// Arrange
|
||||
var type = typeof(ControllerActionArgumentBinderTests);
|
||||
var methodInfo = type.GetMethod(actionMethodName);
|
||||
var actionContext = new ActionContext(new RouteContext(Mock.Of<HttpContext>()),
|
||||
Mock.Of<ActionDescriptor>());
|
||||
|
||||
var actionContext = new ActionContext(
|
||||
new RouteContext(Mock.Of<HttpContext>()),
|
||||
Mock.Of<ActionDescriptor>());
|
||||
|
||||
var metadataProvider = new DataAnnotationsModelMetadataProvider();
|
||||
var modelMetadata = metadataProvider.GetMetadataForParameter(modelAccessor: null,
|
||||
methodInfo: methodInfo,
|
||||
parameterName: "parameter");
|
||||
|
||||
|
||||
var actionBindingContext = new ActionBindingContext(actionContext,
|
||||
Mock.Of<IModelMetadataProvider>(),
|
||||
Mock.Of<IModelBinder>(),
|
||||
Mock.Of<IValueProvider>(),
|
||||
Mock.Of<IInputFormatterSelector>(),
|
||||
Mock.Of<IModelValidatorProvider>());
|
||||
// Act
|
||||
var context = DefaultControllerActionArgumentBinder.GetModelBindingContext(
|
||||
modelMetadata, actionBindingContext, Mock.Of<OperationBindingContext>());
|
||||
modelMetadata,
|
||||
actionContext,
|
||||
Mock.Of<OperationBindingContext>());
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedFallToEmptyPrefix, context.FallbackToEmptyPrefix);
|
||||
|
|
@ -147,24 +141,21 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
// Arrange
|
||||
var type = typeof(ControllerActionArgumentBinderTests);
|
||||
var methodInfo = type.GetMethod(actionMethodName);
|
||||
var actionContext = new ActionContext(new RouteContext(Mock.Of<HttpContext>()),
|
||||
Mock.Of<ActionDescriptor>());
|
||||
|
||||
var actionContext = new ActionContext(
|
||||
new RouteContext(Mock.Of<HttpContext>()),
|
||||
Mock.Of<ActionDescriptor>());
|
||||
|
||||
var metadataProvider = new DataAnnotationsModelMetadataProvider();
|
||||
var modelMetadata = metadataProvider.GetMetadataForParameter(modelAccessor: null,
|
||||
methodInfo: methodInfo,
|
||||
parameterName: "parameter1");
|
||||
|
||||
|
||||
var actionBindingContext = new ActionBindingContext(actionContext,
|
||||
Mock.Of<IModelMetadataProvider>(),
|
||||
Mock.Of<IModelBinder>(),
|
||||
Mock.Of<IValueProvider>(),
|
||||
Mock.Of<IInputFormatterSelector>(),
|
||||
Mock.Of<IModelValidatorProvider>());
|
||||
// Act
|
||||
var context = DefaultControllerActionArgumentBinder.GetModelBindingContext(
|
||||
modelMetadata, actionBindingContext, Mock.Of<OperationBindingContext>());
|
||||
modelMetadata,
|
||||
actionContext,
|
||||
Mock.Of<OperationBindingContext>());
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedFallToEmptyPrefix, context.FallbackToEmptyPrefix);
|
||||
|
|
@ -188,30 +179,33 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
}
|
||||
}
|
||||
};
|
||||
var binder = new Mock<IModelBinder>();
|
||||
binder.Setup(b => b.BindModelAsync(It.IsAny<ModelBindingContext>()))
|
||||
.Returns(Task.FromResult(result: false));
|
||||
var actionContext = new ActionContext(new RouteContext(Mock.Of<HttpContext>()),
|
||||
actionDescriptor);
|
||||
actionContext.Controller = Mock.Of<object>();
|
||||
var bindingContext = new ActionBindingContext(actionContext,
|
||||
Mock.Of<IModelMetadataProvider>(),
|
||||
binder.Object,
|
||||
Mock.Of<IValueProvider>(),
|
||||
Mock.Of<IInputFormatterSelector>(),
|
||||
Mock.Of<IModelValidatorProvider>());
|
||||
var inputFormattersProvider = new Mock<IInputFormattersProvider>();
|
||||
inputFormattersProvider.SetupGet(o => o.InputFormatters)
|
||||
.Returns(new List<IInputFormatter>());
|
||||
var actionBindingContextProvider = new Mock<IActionBindingContextProvider>();
|
||||
actionBindingContextProvider.Setup(p => p.GetActionBindingContextAsync(It.IsAny<ActionContext>()))
|
||||
.Returns(Task.FromResult(bindingContext));
|
||||
|
||||
var invoker = new DefaultControllerActionArgumentBinder(
|
||||
actionBindingContextProvider.Object);
|
||||
var binder = new Mock<IModelBinder>();
|
||||
binder
|
||||
.Setup(b => b.BindModelAsync(It.IsAny<ModelBindingContext>()))
|
||||
.Returns(Task.FromResult(result: false));
|
||||
|
||||
var actionContext = new ActionContext(
|
||||
new RouteContext(Mock.Of<HttpContext>()),
|
||||
actionDescriptor)
|
||||
{
|
||||
Controller = Mock.Of<object>(),
|
||||
};
|
||||
|
||||
var actionBindingContext = new ActionBindingContext()
|
||||
{
|
||||
ModelBinder = binder.Object,
|
||||
};
|
||||
|
||||
var inputFormattersProvider = new Mock<IInputFormattersProvider>();
|
||||
inputFormattersProvider
|
||||
.SetupGet(o => o.InputFormatters)
|
||||
.Returns(new List<IInputFormatter>());
|
||||
|
||||
var invoker = new DefaultControllerActionArgumentBinder(new DataAnnotationsModelMetadataProvider());
|
||||
|
||||
// Act
|
||||
var result = await invoker.GetActionArgumentsAsync(actionContext);
|
||||
var result = await invoker.GetActionArgumentsAsync(actionContext, actionBindingContext);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result);
|
||||
|
|
@ -226,44 +220,47 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
{
|
||||
MethodInfo = method.Method,
|
||||
Parameters = new List<ParameterDescriptor>
|
||||
{
|
||||
new ParameterDescriptor
|
||||
{
|
||||
Name = "foo",
|
||||
ParameterType = typeof(string),
|
||||
}
|
||||
}
|
||||
{
|
||||
new ParameterDescriptor
|
||||
{
|
||||
Name = "foo",
|
||||
ParameterType = typeof(string),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
var value = "Hello world";
|
||||
var binder = new Mock<IModelBinder>();
|
||||
var metadataProvider = new EmptyModelMetadataProvider();
|
||||
binder.Setup(b => b.BindModelAsync(It.IsAny<ModelBindingContext>()))
|
||||
.Callback((ModelBindingContext context) =>
|
||||
{
|
||||
context.ModelMetadata = metadataProvider.GetMetadataForType(modelAccessor: null,
|
||||
modelType: typeof(string));
|
||||
context.Model = value;
|
||||
})
|
||||
.Returns(Task.FromResult(result: true));
|
||||
var actionContext = new ActionContext(new RouteContext(Mock.Of<HttpContext>()),
|
||||
actionDescriptor);
|
||||
actionContext.Controller = Mock.Of<object>();
|
||||
var bindingContext = new ActionBindingContext(actionContext,
|
||||
metadataProvider,
|
||||
binder.Object,
|
||||
Mock.Of<IValueProvider>(),
|
||||
Mock.Of<IInputFormatterSelector>(),
|
||||
Mock.Of<IModelValidatorProvider>());
|
||||
|
||||
var actionBindingContextProvider = new Mock<IActionBindingContextProvider>();
|
||||
actionBindingContextProvider.Setup(p => p.GetActionBindingContextAsync(It.IsAny<ActionContext>()))
|
||||
.Returns(Task.FromResult(bindingContext));
|
||||
var binder = new Mock<IModelBinder>();
|
||||
binder
|
||||
.Setup(b => b.BindModelAsync(It.IsAny<ModelBindingContext>()))
|
||||
.Callback((ModelBindingContext context) =>
|
||||
{
|
||||
context.ModelMetadata = metadataProvider.GetMetadataForType(
|
||||
modelAccessor: null,
|
||||
modelType: typeof(string));
|
||||
|
||||
var invoker = new DefaultControllerActionArgumentBinder(
|
||||
actionBindingContextProvider.Object);
|
||||
context.Model = value;
|
||||
})
|
||||
.Returns(Task.FromResult(result: true));
|
||||
|
||||
var actionContext = new ActionContext(
|
||||
new RouteContext(Mock.Of<HttpContext>()),
|
||||
actionDescriptor)
|
||||
{
|
||||
Controller = Mock.Of<object>(),
|
||||
};
|
||||
|
||||
var actionBindingContext = new ActionBindingContext()
|
||||
{
|
||||
ModelBinder = binder.Object,
|
||||
};
|
||||
|
||||
var invoker = new DefaultControllerActionArgumentBinder(metadataProvider);
|
||||
|
||||
// Act
|
||||
var result = await invoker.GetActionArgumentsAsync(actionContext);
|
||||
var result = await invoker.GetActionArgumentsAsync(actionContext, actionBindingContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1, result.Count);
|
||||
|
|
@ -291,6 +288,11 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
}
|
||||
}
|
||||
|
||||
private class Person
|
||||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
private class NonValueProviderBinderMetadataAttribute : Attribute, IBinderMetadata
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -468,10 +468,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
|
||||
private static IModelBinder GetCompositeBinder(params IModelBinder[] binders)
|
||||
{
|
||||
var binderProvider = new Mock<IModelBinderProvider>();
|
||||
binderProvider.SetupGet(p => p.ModelBinders)
|
||||
.Returns(binders);
|
||||
return new CompositeModelBinder(binderProvider.Object);
|
||||
return new CompositeModelBinder(binders);
|
||||
}
|
||||
|
||||
public class User
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ using Microsoft.AspNet.Routing;
|
|||
using Microsoft.AspNet.Security.DataProtection;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Moq;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Rendering
|
||||
{
|
||||
|
|
@ -143,6 +144,14 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
var httpContext = new DefaultHttpContext();
|
||||
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
||||
|
||||
var bindingContext = new ActionBindingContext()
|
||||
{
|
||||
ValidatorProvider = new DataAnnotationsModelValidatorProvider(),
|
||||
};
|
||||
|
||||
var bindingContextAccessor = new MockScopedInstance<ActionBindingContext>();
|
||||
bindingContextAccessor.Value = bindingContext;
|
||||
|
||||
var serviceProvider = new Mock<IServiceProvider>();
|
||||
serviceProvider
|
||||
.Setup(s => s.GetService(typeof(ICompositeViewEngine)))
|
||||
|
|
@ -157,21 +166,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
httpContext.RequestServices = serviceProvider.Object;
|
||||
if (htmlGenerator == null)
|
||||
{
|
||||
var actionBindingContext = new ActionBindingContext(
|
||||
actionContext,
|
||||
provider,
|
||||
Mock.Of<IModelBinder>(),
|
||||
Mock.Of<IValueProvider>(),
|
||||
Mock.Of<IInputFormatterSelector>(),
|
||||
new DataAnnotationsModelValidatorProvider());
|
||||
var actionBindingContextProvider = new Mock<IActionBindingContextProvider>();
|
||||
actionBindingContextProvider
|
||||
.Setup(c => c.GetActionBindingContextAsync(It.IsAny<ActionContext>()))
|
||||
.Returns(Task.FromResult(actionBindingContext));
|
||||
|
||||
htmlGenerator = new DefaultHtmlGenerator(
|
||||
actionBindingContextProvider.Object,
|
||||
GetAntiForgeryInstance(),
|
||||
bindingContextAccessor,
|
||||
provider,
|
||||
urlHelper);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -711,6 +711,11 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
{
|
||||
}
|
||||
|
||||
private class Person
|
||||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
private class TestViewDataDictionary : ViewDataDictionary
|
||||
{
|
||||
public TestViewDataDictionary(IModelMetadataProvider modelMetadataProvider,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.TestHost;
|
||||
|
|
@ -22,6 +25,39 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
var server = TestServer.Create(_services, _app);
|
||||
var client = server.CreateClient();
|
||||
|
||||
var expected = new string[]
|
||||
{
|
||||
"Controller Override - OnAuthorization",
|
||||
"Global Authorization Filter - OnAuthorization",
|
||||
"On Controller Authorization Filter - OnAuthorization",
|
||||
"Authorize Filter On Action - OnAuthorization",
|
||||
"Controller Override Resource Filter - OnResourceExecuting",
|
||||
"Global Resource Filter - OnResourceExecuting",
|
||||
"Controller Resource Filter - OnResourceExecuting",
|
||||
"Action Resource Filter - OnResourceExecuting",
|
||||
"Controller Override - OnActionExecuting",
|
||||
"Global Action Filter - OnActionExecuting",
|
||||
"On Controller Action Filter - OnActionExecuting",
|
||||
"On Action Action Filter - OnActionExecuting",
|
||||
"Executing Action",
|
||||
"On Action Action Filter - OnActionExecuted",
|
||||
"On Controller Action Filter - OnActionExecuted",
|
||||
"Global Action Filter - OnActionExecuted",
|
||||
"Controller Override - OnActionExecuted",
|
||||
"Controller Override - OnResultExecuting",
|
||||
"Global Result Filter - OnResultExecuted",
|
||||
"On Controller Result Filter - OnResultExecuting",
|
||||
"On Action Result Filter - OnResultExecuting",
|
||||
"On Action Result Filter - OnResultExecuted",
|
||||
"On Controller Result Filter - OnResultExecuted",
|
||||
"Global Result Filter - OnResultExecuted",
|
||||
"Controller Override - OnResultExecuted",
|
||||
"Action Resource Filter - OnResourceExecuted",
|
||||
"Controller Resource Filter - OnResourceExecuted",
|
||||
"Global Resource Filter - OnResourceExecuted",
|
||||
"Controller Override Resource Filter - OnResourceExecuted",
|
||||
};
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("http://localhost/Products/GetPrice/5");
|
||||
|
||||
|
|
@ -30,30 +66,15 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
|
||||
var filters = response.Headers.GetValues("filters");
|
||||
Assert.Equal(
|
||||
"Controller Override - OnAuthorization," +
|
||||
"Global Authorization Filter - OnAuthorization," +
|
||||
"On Controller Authorization Filter - OnAuthorization," +
|
||||
"Authorize Filter On Action - OnAuthorization," +
|
||||
"Controller Override - OnActionExecuting," +
|
||||
"Global Action Filter - OnActionExecuting," +
|
||||
"On Controller Action Filter - OnActionExecuting," +
|
||||
"On Action Action Filter - OnActionExecuting," +
|
||||
"Executing Action," +
|
||||
"On Action Action Filter - OnActionExecuted," +
|
||||
"On Controller Action Filter - OnActionExecuted," +
|
||||
"Global Action Filter - OnActionExecuted," +
|
||||
"Controller Override - OnActionExecuted," +
|
||||
"Controller Override - OnResultExecuting," +
|
||||
"Global Result Filter - OnResultExecuted," +
|
||||
"On Controller Result Filter - OnResultExecuting," +
|
||||
"On Action Result Filter - OnResultExecuting," +
|
||||
"On Action Result Filter - OnResultExecuted," +
|
||||
"On Controller Result Filter - OnResultExecuted," +
|
||||
"Global Result Filter - OnResultExecuted," +
|
||||
"Controller Override - OnResultExecuted",
|
||||
(filters as string[])[0]);
|
||||
var filters = response.Headers.GetValues("filters").Single().Split(',');
|
||||
|
||||
var i = 0;
|
||||
foreach (var filter in filters)
|
||||
{
|
||||
Assert.Equal(filter, expected[i++]);
|
||||
}
|
||||
|
||||
Assert.Equal(expected.Length, filters.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -531,5 +552,50 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal("Throwing Exception Filter", await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResourceFilter_ChangesInputFormatters_JsonAccepted()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ sampleInt: 10 }";
|
||||
|
||||
var server = TestServer.Create(_services, _app);
|
||||
var client = server.CreateClient();
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/Json");
|
||||
request.Content = new StringContent(input, Encoding.UTF8, "application/json");
|
||||
|
||||
// Act
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal("10", await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResourceFilter_ChangesInputFormatters_XmlDenied()
|
||||
{
|
||||
// Arrange
|
||||
var input =
|
||||
"<DummyClass xmlns=\"http://schemas.datacontract.org/2004/07/FormatterWebSite\">" +
|
||||
"<SampleInt>10</SampleInt>" +
|
||||
"</DummyClass>";
|
||||
|
||||
// There's nothing that can deserialize the body, so the result contains the default
|
||||
// value.
|
||||
var server = TestServer.Create(_services, _app);
|
||||
var client = server.CreateClient();
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/Json");
|
||||
request.Content = new StringContent(input, Encoding.UTF8, "application/xml");
|
||||
|
||||
// Act
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal("0", await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -343,20 +343,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
new TypeConverterModelBinder(),
|
||||
new MutableObjectModelBinder()
|
||||
};
|
||||
var binderProviders = new Mock<IModelBinderProvider>();
|
||||
binderProviders.SetupGet(p => p.ModelBinders)
|
||||
.Returns(binders);
|
||||
var binder = new CompositeModelBinder(binderProviders.Object);
|
||||
|
||||
var binder = new CompositeModelBinder(binders);
|
||||
return binder;
|
||||
}
|
||||
|
||||
private static CompositeModelBinder CreateCompositeBinder(IModelBinder mockIntBinder)
|
||||
{
|
||||
var binderProvider = new Mock<IModelBinderProvider>();
|
||||
binderProvider.SetupGet(p => p.ModelBinders)
|
||||
.Returns(new[] { mockIntBinder });
|
||||
|
||||
var shimBinder = new CompositeModelBinder(binderProvider.Object);
|
||||
var shimBinder = new CompositeModelBinder(new[] { mockIntBinder });
|
||||
return shimBinder;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,10 +50,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
public async Task BindModel_SubBindingSucceeds()
|
||||
{
|
||||
// Arrange
|
||||
var binderProviders = new Mock<IModelBinderProvider>();
|
||||
binderProviders.SetupGet(b => b.ModelBinders)
|
||||
.Returns(new[] { CreateStringBinder(), CreateIntBinder() });
|
||||
var innerBinder = new CompositeModelBinder(binderProviders.Object);
|
||||
var innerBinder = new CompositeModelBinder(new[] { CreateStringBinder(), CreateIntBinder() });
|
||||
var valueProvider = new SimpleHttpValueProvider();
|
||||
var bindingContext = GetBindingContext(valueProvider, innerBinder);
|
||||
|
||||
|
|
|
|||
|
|
@ -1205,13 +1205,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
|
||||
private static ModelBindingContext CreateContext(ModelMetadata metadata)
|
||||
{
|
||||
var provider = new Mock<IModelValidatorProviderProvider>();
|
||||
provider.SetupGet(p => p.ModelValidatorProviders)
|
||||
.Returns(new IModelValidatorProvider[]
|
||||
{
|
||||
new DataAnnotationsModelValidatorProvider(),
|
||||
new DataMemberModelValidatorProvider()
|
||||
});
|
||||
var providers = new IModelValidatorProvider[]
|
||||
{
|
||||
new DataAnnotationsModelValidatorProvider(),
|
||||
new DataMemberModelValidatorProvider()
|
||||
};
|
||||
|
||||
return new ModelBindingContext
|
||||
{
|
||||
|
|
@ -1220,7 +1218,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
ModelName = "theModel",
|
||||
OperationBindingContext = new OperationBindingContext
|
||||
{
|
||||
ValidatorProvider = new CompositeModelValidatorProvider(provider.Object)
|
||||
ValidatorProvider = new CompositeModelValidatorProvider(providers)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
var provider2 = new Mock<IModelValidatorProvider>();
|
||||
provider2.Setup(p => p.GetValidators(It.IsAny<ModelMetadata>()))
|
||||
.Returns(new[] { validator3 });
|
||||
var providerProvider = new Mock<IModelValidatorProviderProvider>();
|
||||
providerProvider.Setup(p => p.ModelValidatorProviders)
|
||||
.Returns(new[] { provider1.Object, provider2.Object });
|
||||
var compositeModelValidator = new CompositeModelValidatorProvider(providerProvider.Object);
|
||||
var compositeModelValidator = new CompositeModelValidatorProvider(new[] { provider1.Object, provider2.Object });
|
||||
var modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(
|
||||
modelAccessor: null,
|
||||
modelType: typeof(string));
|
||||
|
|
|
|||
|
|
@ -336,13 +336,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
object model, Type type, List<Type> excludedTypes = null)
|
||||
{
|
||||
var modelStateDictionary = new ModelStateDictionary();
|
||||
var provider = new Mock<IModelValidatorProviderProvider>();
|
||||
provider.SetupGet(p => p.ModelValidatorProviders)
|
||||
.Returns(new IModelValidatorProvider[]
|
||||
{
|
||||
new DataAnnotationsModelValidatorProvider(),
|
||||
new DataMemberModelValidatorProvider()
|
||||
});
|
||||
var providers = new IModelValidatorProvider[]
|
||||
{
|
||||
new DataAnnotationsModelValidatorProvider(),
|
||||
new DataMemberModelValidatorProvider()
|
||||
};
|
||||
var modelMetadataProvider = new EmptyModelMetadataProvider();
|
||||
var excludedValidationTypesPredicate =
|
||||
new List<IExcludeTypeValidationFilter>();
|
||||
|
|
@ -358,7 +356,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
|
||||
return new ModelValidationContext(
|
||||
modelMetadataProvider,
|
||||
new CompositeModelValidatorProvider(provider.Object),
|
||||
new CompositeModelValidatorProvider(providers),
|
||||
modelStateDictionary,
|
||||
new ModelMetadata(
|
||||
provider: modelMetadataProvider,
|
||||
|
|
|
|||
|
|
@ -356,12 +356,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
new DataMemberModelValidatorProvider()
|
||||
};
|
||||
|
||||
var provider = new Mock<IModelValidatorProviderProvider>();
|
||||
provider.SetupGet(p => p.ModelValidatorProviders)
|
||||
.Returns(providers);
|
||||
|
||||
return new ModelValidationContext(new EmptyModelMetadataProvider(),
|
||||
new CompositeModelValidatorProvider(provider.Object),
|
||||
new CompositeModelValidatorProvider(providers),
|
||||
new ModelStateDictionary(),
|
||||
metadata,
|
||||
null);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using Microsoft.AspNet.Mvc.Rendering;
|
|||
using Microsoft.AspNet.PipelineCore;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.AspNet.Security.DataProtection;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Moq;
|
||||
|
||||
|
|
@ -26,6 +27,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
public TestableHtmlGenerator(IModelMetadataProvider metadataProvider, IUrlHelper urlHelper)
|
||||
: this(
|
||||
metadataProvider,
|
||||
Mock.Of<IContextAccessor<ActionBindingContext>>(),
|
||||
urlHelper,
|
||||
validationAttributes: new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
|
|
@ -33,9 +35,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
|
||||
public TestableHtmlGenerator(
|
||||
IModelMetadataProvider metadataProvider,
|
||||
IContextAccessor<ActionBindingContext> bindingContextAccessor,
|
||||
IUrlHelper urlHelper,
|
||||
IDictionary<string, object> validationAttributes)
|
||||
: base(Mock.Of<IActionBindingContextProvider>(), GetAntiForgery(), metadataProvider, urlHelper)
|
||||
: base(GetAntiForgery(), bindingContextAccessor, metadataProvider, urlHelper)
|
||||
{
|
||||
_validationAttributes = validationAttributes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
// 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.Linq;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace FiltersWebSite.Controllers
|
||||
{
|
||||
[Route("Json")]
|
||||
public class JsonOnlyController : Controller, IResourceFilter
|
||||
{
|
||||
[HttpPost]
|
||||
public string Post([FromBody] DummyClass dummy)
|
||||
{
|
||||
return (dummy?.SampleInt ?? 0).ToString();
|
||||
}
|
||||
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||
{
|
||||
var jsonFormatter = context.InputFormatters.OfType<JsonInputFormatter>().Single();
|
||||
|
||||
context.InputFormatters.Clear();
|
||||
context.InputFormatters.Add(jsonFormatter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,11 +10,13 @@ namespace FiltersWebSite
|
|||
[ControllerResultFilter]
|
||||
[ControllerActionFilter]
|
||||
[ControllerAuthorizationFilter]
|
||||
public class ProductsController : Controller, IResultFilter, IAuthorizationFilter
|
||||
[TracingResourceFilter("Controller Resource Filter")]
|
||||
public class ProductsController : Controller, IResultFilter, IAuthorizationFilter, IResourceFilter
|
||||
{
|
||||
[PassThroughResultFilter]
|
||||
[PassThroughActionFilter]
|
||||
[AuthorizeUser]
|
||||
[TracingResourceFilter("Action Resource Filter")]
|
||||
public IActionResult GetPrice(int id)
|
||||
{
|
||||
Response.Headers.Append("filters", "Executing Action");
|
||||
|
|
@ -47,5 +49,19 @@ namespace FiltersWebSite
|
|||
{
|
||||
context.HttpContext.Response.Headers.Append("filters", "Controller Override - OnAuthorization");
|
||||
}
|
||||
|
||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||
{
|
||||
context.HttpContext.Response.Headers.Append(
|
||||
"filters",
|
||||
"Controller Override Resource Filter - OnResourceExecuting");
|
||||
}
|
||||
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
{
|
||||
context.HttpContext.Response.Headers.Append(
|
||||
"filters",
|
||||
"Controller Override Resource Filter - OnResourceExecuted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// 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.Mvc;
|
||||
|
||||
namespace FiltersWebSite
|
||||
{
|
||||
public class TracingResourceFilter : Attribute, IResourceFilter
|
||||
{
|
||||
public TracingResourceFilter(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
{
|
||||
context.HttpContext.Response.Headers.Append(
|
||||
"filters",
|
||||
Name + " - OnResourceExecuted");
|
||||
}
|
||||
|
||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||
{
|
||||
context.HttpContext.Response.Headers.Append(
|
||||
"filters",
|
||||
Name + " - OnResourceExecuting");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ namespace FiltersWebSite
|
|||
options.Filters.Add(new GlobalActionFilter());
|
||||
options.Filters.Add(new GlobalResultFilter());
|
||||
options.Filters.Add(new GlobalAuthorizationFilter());
|
||||
options.Filters.Add(new TracingResourceFilter("Global Resource Filter"));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue