Added ValueProviderFactories to ResourceFilterExecutingContext
This enables removing value provider factories from model binding(which is needed in some scenarios like large file uploads)
This commit is contained in:
parent
df4eb283b2
commit
20a2e748ec
|
|
@ -31,6 +31,10 @@
|
|||
"imports": [
|
||||
"portable-net45+wp80+win8+wpa81+dnxcore50"
|
||||
]
|
||||
},
|
||||
"Microsoft.DotNet.Watcher.Tools": {
|
||||
"version": "1.0.0-*",
|
||||
"imports": "portable-net451+win8"
|
||||
}
|
||||
},
|
||||
"frameworks": {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Filters
|
||||
{
|
||||
|
|
@ -16,9 +18,19 @@ namespace Microsoft.AspNetCore.Mvc.Filters
|
|||
/// </summary>
|
||||
/// <param name="actionContext">The <see cref="ActionContext"/>.</param>
|
||||
/// <param name="filters">The list of <see cref="IFilterMetadata"/> instances.</param>
|
||||
public ResourceExecutingContext(ActionContext actionContext, IList<IFilterMetadata> filters)
|
||||
/// <param name="valueProviderFactories">The list of <see cref="IValueProviderFactory"/> instances.</param>
|
||||
public ResourceExecutingContext(
|
||||
ActionContext actionContext,
|
||||
IList<IFilterMetadata> filters,
|
||||
IList<IValueProviderFactory> valueProviderFactories)
|
||||
: base(actionContext, filters)
|
||||
{
|
||||
if (valueProviderFactories == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(valueProviderFactories));
|
||||
}
|
||||
|
||||
ValueProviderFactories = valueProviderFactories;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -29,5 +41,10 @@ namespace Microsoft.AspNetCore.Mvc.Filters
|
|||
/// short-circuit execution of additional resource filters and the action itself.
|
||||
/// </remarks>
|
||||
public virtual IActionResult Result { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of <see cref="IValueProviderFactory"/> instances used by model binding.
|
||||
/// </summary>
|
||||
public IList<IValueProviderFactory> ValueProviderFactories { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
{
|
||||
throw new ArgumentNullException(nameof(valueProviderFactories));
|
||||
}
|
||||
|
||||
|
||||
_controllerFactory = controllerFactory;
|
||||
_controllerArgumentBinder = controllerArgumentBinder;
|
||||
_logger = logger;
|
||||
|
|
@ -216,7 +216,11 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
{
|
||||
_cursor.Reset();
|
||||
|
||||
_resourceExecutingContext = new ResourceExecutingContext(_controllerContext, _filters);
|
||||
_resourceExecutingContext = new ResourceExecutingContext(
|
||||
_controllerContext,
|
||||
_filters,
|
||||
_controllerContext.ValueProviderFactories);
|
||||
|
||||
return InvokeResourceFilterAsync();
|
||||
}
|
||||
|
||||
|
|
@ -266,7 +270,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
}
|
||||
|
||||
_diagnosticSource.AfterOnResourceExecution(_resourceExecutedContext, item.FilterAsync);
|
||||
|
||||
|
||||
if (_resourceExecutingContext.Result != null)
|
||||
{
|
||||
_logger.ResourceFilterShortCircuited(item.FilterAsync);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
|||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Moq;
|
||||
|
|
@ -309,7 +310,10 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
};
|
||||
var actionContext = new ActionContext(httpContext, new RouteData(), actionWithConstraint);
|
||||
|
||||
var resourceExecutingContext = new ResourceExecutingContext(actionContext, new[] { consumesFilter });
|
||||
var resourceExecutingContext = new ResourceExecutingContext(
|
||||
actionContext,
|
||||
new[] { consumesFilter },
|
||||
new List<IValueProviderFactory>());
|
||||
|
||||
// Act
|
||||
consumesFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
|
|
@ -336,7 +340,10 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
};
|
||||
var actionContext = new ActionContext(httpContext, new RouteData(), actionWithConstraint);
|
||||
|
||||
var resourceExecutingContext = new ResourceExecutingContext(actionContext, new[] { consumesFilter });
|
||||
var resourceExecutingContext = new ResourceExecutingContext(
|
||||
actionContext,
|
||||
new[] { consumesFilter },
|
||||
new List<IValueProviderFactory>());
|
||||
|
||||
// Act
|
||||
consumesFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
|
|
@ -361,7 +368,10 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
new List<FilterDescriptor>() { new FilterDescriptor(consumesFilter, FilterScope.Action) }
|
||||
};
|
||||
var actionContext = new ActionContext(httpContext, new RouteData(), actionWithConstraint);
|
||||
var resourceExecutingContext = new ResourceExecutingContext(actionContext, new[] { consumesFilter });
|
||||
var resourceExecutingContext = new ResourceExecutingContext(
|
||||
actionContext,
|
||||
new[] { consumesFilter },
|
||||
new List<IValueProviderFactory>());
|
||||
|
||||
// Act
|
||||
consumesFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.TestCommon;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
|
@ -87,7 +89,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
|
||||
var resourceExecutingContext = new ResourceExecutingContext(
|
||||
ac,
|
||||
new IFilterMetadata[] { });
|
||||
new IFilterMetadata[] { },
|
||||
new List<IValueProviderFactory>());
|
||||
|
||||
var filter = new FormatFilter(mockObjects.OptionsManager);
|
||||
|
||||
|
|
@ -322,7 +325,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
|
||||
var resourceExecutingContext = new ResourceExecutingContext(
|
||||
actionContext,
|
||||
new IFilterMetadata[] { });
|
||||
new IFilterMetadata[] { },
|
||||
new List<IValueProviderFactory>());
|
||||
|
||||
var filter = new FormatFilter(mockObjects.OptionsManager);
|
||||
|
||||
|
|
@ -356,7 +360,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
|
||||
var resourceExecutingContext = new ResourceExecutingContext(
|
||||
actionContext,
|
||||
new IFilterMetadata[] { });
|
||||
new IFilterMetadata[] { },
|
||||
new List<IValueProviderFactory>());
|
||||
|
||||
var filter = new FormatFilter(mockObjects.OptionsManager);
|
||||
|
||||
|
|
@ -392,7 +397,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
{
|
||||
var context = new ResourceExecutingContext(
|
||||
MockActionContext,
|
||||
filters);
|
||||
filters,
|
||||
new List<IValueProviderFactory>());
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1862,6 +1862,66 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
Assert.False(invoker.ControllerFactory.CreateCalled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddingValueProviderFactory_AtResourceFilter_IsAvailableInControllerContext()
|
||||
{
|
||||
// Arrange
|
||||
var valueProviderFactory2 = Mock.Of<IValueProviderFactory>();
|
||||
var resourceFilter = new Mock<IResourceFilter>();
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecuting(It.IsAny<ResourceExecutingContext>()))
|
||||
.Callback<ResourceExecutingContext>((resourceExecutingContext) =>
|
||||
{
|
||||
resourceExecutingContext.ValueProviderFactories.Add(valueProviderFactory2);
|
||||
});
|
||||
var valueProviderFactory1 = Mock.Of<IValueProviderFactory>();
|
||||
var valueProviderFactories = new List<IValueProviderFactory>();
|
||||
valueProviderFactories.Add(valueProviderFactory1);
|
||||
|
||||
var invoker = CreateInvoker(
|
||||
new IFilterMetadata[] { resourceFilter.Object }, valueProviderFactories: valueProviderFactories);
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
var controllerContext = invoker.ControllerFactory.ControllerContext;
|
||||
Assert.NotNull(controllerContext);
|
||||
Assert.Equal(2, controllerContext.ValueProviderFactories.Count);
|
||||
Assert.Same(valueProviderFactory1, controllerContext.ValueProviderFactories[0]);
|
||||
Assert.Same(valueProviderFactory2, controllerContext.ValueProviderFactories[1]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeletingValueProviderFactory_AtResourceFilter_IsNotAvailableInControllerContext()
|
||||
{
|
||||
// Arrange
|
||||
var resourceFilter = new Mock<IResourceFilter>();
|
||||
resourceFilter
|
||||
.Setup(f => f.OnResourceExecuting(It.IsAny<ResourceExecutingContext>()))
|
||||
.Callback<ResourceExecutingContext>((resourceExecutingContext) =>
|
||||
{
|
||||
resourceExecutingContext.ValueProviderFactories.RemoveAt(0);
|
||||
});
|
||||
var valueProviderFactory1 = Mock.Of<IValueProviderFactory>();
|
||||
var valueProviderFactory2 = Mock.Of<IValueProviderFactory>();
|
||||
var valueProviderFactories = new List<IValueProviderFactory>();
|
||||
valueProviderFactories.Add(valueProviderFactory1);
|
||||
valueProviderFactories.Add(valueProviderFactory2);
|
||||
|
||||
var invoker = CreateInvoker(
|
||||
new IFilterMetadata[] { resourceFilter.Object }, valueProviderFactories: valueProviderFactories);
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
var controllerContext = invoker.ControllerFactory.ControllerContext;
|
||||
Assert.NotNull(controllerContext);
|
||||
Assert.Equal(1, controllerContext.ValueProviderFactories.Count);
|
||||
Assert.Same(valueProviderFactory2, controllerContext.ValueProviderFactories[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MaxAllowedErrorsIsSet_BeforeCallingAuthorizationFilter()
|
||||
{
|
||||
|
|
@ -2038,8 +2098,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
.Verifiable();
|
||||
|
||||
var invoker = CreateInvoker(
|
||||
new[] { filter.Object },
|
||||
nameof(TestController.EchoWithException),
|
||||
new[] { filter.Object },
|
||||
nameof(TestController.EchoWithException),
|
||||
new Dictionary<string, object>() { { "input", inputString } });
|
||||
|
||||
// Act & Assert
|
||||
|
|
@ -2061,8 +2121,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
.Verifiable();
|
||||
|
||||
var invoker = CreateInvoker(
|
||||
new[] { filter.Object },
|
||||
nameof(TestController.EchoWithDefaultValue),
|
||||
new[] { filter.Object },
|
||||
nameof(TestController.EchoWithDefaultValue),
|
||||
new Dictionary<string, object>());
|
||||
|
||||
// Act
|
||||
|
|
@ -2088,7 +2148,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
.Verifiable();
|
||||
|
||||
var invoker = CreateInvoker(
|
||||
new[] { filter.Object },
|
||||
new[] { filter.Object },
|
||||
nameof(TestController.EchoWithDefaultValue),
|
||||
new Dictionary<string, object>() { { "input", inputString } });
|
||||
|
||||
|
|
@ -2360,18 +2420,80 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
+ "'.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Invoke_UsesDefaultValuesIfNotBound()
|
||||
{
|
||||
// Arrange
|
||||
var actionDescriptor = new ControllerActionDescriptor
|
||||
{
|
||||
ControllerTypeInfo = typeof(TestController).GetTypeInfo(),
|
||||
BoundProperties = new List<ParameterDescriptor>(),
|
||||
MethodInfo = typeof(TestController).GetTypeInfo()
|
||||
.DeclaredMethods
|
||||
.First(m => m.Name.Equals("ActionMethodWithDefaultValues", StringComparison.Ordinal)),
|
||||
|
||||
Parameters = new List<ParameterDescriptor>
|
||||
{
|
||||
new ParameterDescriptor
|
||||
{
|
||||
Name = "value",
|
||||
ParameterType = typeof(int),
|
||||
BindingInfo = new BindingInfo(),
|
||||
}
|
||||
},
|
||||
FilterDescriptors = new List<FilterDescriptor>()
|
||||
};
|
||||
|
||||
var context = new Mock<HttpContext>();
|
||||
context.SetupGet(c => c.Items)
|
||||
.Returns(new Dictionary<object, object>());
|
||||
context.Setup(c => c.RequestServices.GetService(typeof(ILoggerFactory)))
|
||||
.Returns(new NullLoggerFactory());
|
||||
|
||||
var actionContext = new ActionContext(context.Object, new RouteData(), actionDescriptor);
|
||||
|
||||
var controllerFactory = new Mock<IControllerFactory>();
|
||||
controllerFactory.Setup(c => c.CreateController(It.IsAny<ControllerContext>()))
|
||||
.Returns(new TestController());
|
||||
|
||||
var metadataProvider = new EmptyModelMetadataProvider();
|
||||
|
||||
var argumentBinder = new ControllerArgumentBinder(
|
||||
metadataProvider,
|
||||
TestModelBinderFactory.CreateDefault(metadataProvider),
|
||||
new DefaultObjectValidator(metadataProvider, new IModelValidatorProvider[0]));
|
||||
|
||||
var invoker = new ControllerActionInvoker(
|
||||
CreateFilterCache(),
|
||||
controllerFactory.Object,
|
||||
argumentBinder,
|
||||
new NullLoggerFactory().CreateLogger<ControllerActionInvoker>(),
|
||||
new DiagnosticListener("Microsoft.AspNetCore"),
|
||||
actionContext,
|
||||
new IValueProviderFactory[0],
|
||||
200);
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(5, context.Object.Items["Result"]);
|
||||
}
|
||||
|
||||
private TestControllerActionInvoker CreateInvoker(
|
||||
IFilterMetadata filter,
|
||||
bool actionThrows = false,
|
||||
int maxAllowedErrorsInModelState = 200)
|
||||
int maxAllowedErrorsInModelState = 200,
|
||||
List<IValueProviderFactory> valueProviderFactories = null)
|
||||
{
|
||||
return CreateInvoker(new[] { filter }, actionThrows, maxAllowedErrorsInModelState);
|
||||
return CreateInvoker(new[] { filter }, actionThrows, maxAllowedErrorsInModelState, valueProviderFactories);
|
||||
}
|
||||
|
||||
private TestControllerActionInvoker CreateInvoker(
|
||||
IFilterMetadata[] filters,
|
||||
bool actionThrows = false,
|
||||
int maxAllowedErrorsInModelState = 200)
|
||||
int maxAllowedErrorsInModelState = 200,
|
||||
List<IValueProviderFactory> valueProviderFactories = null)
|
||||
{
|
||||
var actionDescriptor = new ControllerActionDescriptor()
|
||||
{
|
||||
|
|
@ -2381,15 +2503,18 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
if (actionThrows)
|
||||
{
|
||||
actionDescriptor.MethodInfo = typeof(ControllerActionInvokerTest).GetMethod(nameof(ControllerActionInvokerTest.ThrowingActionMethod));
|
||||
actionDescriptor.MethodInfo = typeof(ControllerActionInvokerTest).GetMethod(
|
||||
nameof(ControllerActionInvokerTest.ThrowingActionMethod));
|
||||
}
|
||||
else
|
||||
{
|
||||
actionDescriptor.MethodInfo = typeof(ControllerActionInvokerTest).GetMethod(nameof(ControllerActionInvokerTest.ActionMethod));
|
||||
actionDescriptor.MethodInfo = typeof(ControllerActionInvokerTest).GetMethod(
|
||||
nameof(ControllerActionInvokerTest.ActionMethod));
|
||||
}
|
||||
actionDescriptor.ControllerTypeInfo = typeof(ControllerActionInvokerTest).GetTypeInfo();
|
||||
|
||||
return CreateInvoker(filters, actionDescriptor, null, null, maxAllowedErrorsInModelState);
|
||||
return CreateInvoker(
|
||||
filters, actionDescriptor, null, null, maxAllowedErrorsInModelState, valueProviderFactories);
|
||||
}
|
||||
|
||||
private TestControllerActionInvoker CreateInvoker(
|
||||
|
|
@ -2417,7 +2542,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
ControllerActionDescriptor actionDescriptor,
|
||||
IControllerArgumentBinder controllerArgumentBinder,
|
||||
object controller,
|
||||
int maxAllowedErrorsInModelState = 200)
|
||||
int maxAllowedErrorsInModelState = 200,
|
||||
List<IValueProviderFactory> valueProviderFactories = null)
|
||||
{
|
||||
var httpContext = new Mock<HttpContext>(MockBehavior.Loose);
|
||||
|
||||
|
|
@ -2512,6 +2638,11 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
.SetupGet(fp => fp.Order)
|
||||
.Returns(-1000);
|
||||
|
||||
if (valueProviderFactories == null)
|
||||
{
|
||||
valueProviderFactories = new List<IValueProviderFactory>();
|
||||
}
|
||||
|
||||
var invoker = new TestControllerActionInvoker(
|
||||
new[] { filterProvider.Object },
|
||||
new MockControllerFactory(controller ?? this),
|
||||
|
|
@ -2519,72 +2650,11 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
new NullLoggerFactory().CreateLogger<ControllerActionInvoker>(),
|
||||
new DiagnosticListener("Microsoft.AspNetCore"),
|
||||
actionContext,
|
||||
new IValueProviderFactory[0],
|
||||
valueProviderFactories.AsReadOnly(),
|
||||
maxAllowedErrorsInModelState);
|
||||
return invoker;
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task Invoke_UsesDefaultValuesIfNotBound()
|
||||
{
|
||||
// Arrange
|
||||
var actionDescriptor = new ControllerActionDescriptor
|
||||
{
|
||||
ControllerTypeInfo = typeof(TestController).GetTypeInfo(),
|
||||
BoundProperties = new List<ParameterDescriptor>(),
|
||||
MethodInfo = typeof(TestController).GetTypeInfo()
|
||||
.DeclaredMethods
|
||||
.First(m => m.Name.Equals("ActionMethodWithDefaultValues", StringComparison.Ordinal)),
|
||||
|
||||
Parameters = new List<ParameterDescriptor>
|
||||
{
|
||||
new ParameterDescriptor
|
||||
{
|
||||
Name = "value",
|
||||
ParameterType = typeof(int),
|
||||
BindingInfo = new BindingInfo(),
|
||||
}
|
||||
},
|
||||
FilterDescriptors = new List<FilterDescriptor>()
|
||||
};
|
||||
|
||||
var context = new Mock<HttpContext>();
|
||||
context.SetupGet(c => c.Items)
|
||||
.Returns(new Dictionary<object, object>());
|
||||
context.Setup(c => c.RequestServices.GetService(typeof(ILoggerFactory)))
|
||||
.Returns(new NullLoggerFactory());
|
||||
|
||||
var actionContext = new ActionContext(context.Object, new RouteData(), actionDescriptor);
|
||||
|
||||
var controllerFactory = new Mock<IControllerFactory>();
|
||||
controllerFactory.Setup(c => c.CreateController(It.IsAny<ControllerContext>()))
|
||||
.Returns(new TestController());
|
||||
|
||||
var metadataProvider = new EmptyModelMetadataProvider();
|
||||
|
||||
var argumentBinder = new ControllerArgumentBinder(
|
||||
metadataProvider,
|
||||
TestModelBinderFactory.CreateDefault(metadataProvider),
|
||||
new DefaultObjectValidator(metadataProvider, new IModelValidatorProvider[0]));
|
||||
|
||||
var invoker = new ControllerActionInvoker(
|
||||
CreateFilterCache(),
|
||||
controllerFactory.Object,
|
||||
argumentBinder,
|
||||
new NullLoggerFactory().CreateLogger<ControllerActionInvoker>(),
|
||||
new DiagnosticListener("Microsoft.AspNetCore"),
|
||||
actionContext,
|
||||
new IValueProviderFactory[0],
|
||||
200);
|
||||
|
||||
// Act
|
||||
await invoker.InvokeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(5, context.Object.Items["Result"]);
|
||||
}
|
||||
|
||||
public IActionResult ActionMethod()
|
||||
{
|
||||
return _result;
|
||||
|
|
@ -2785,8 +2855,11 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
public bool ReleaseCalled { get; private set; }
|
||||
|
||||
public ControllerContext ControllerContext { get; private set; }
|
||||
|
||||
public object CreateController(ControllerContext context)
|
||||
{
|
||||
ControllerContext = context;
|
||||
CreateCalled = true;
|
||||
return _controller;
|
||||
}
|
||||
|
|
@ -2886,6 +2959,5 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
return TaskCache.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// 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.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
|
|
@ -106,7 +107,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
public async Task CanAuthorize(string testAction)
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/AuthorizeUser/"+testAction);
|
||||
var response = await Client.GetAsync("http://localhost/AuthorizeUser/" + testAction);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
|
@ -509,5 +510,31 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
|
||||
Assert.Equal("\"someValue\"", await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResourceFilter_RemovingValueProviderFactoriesForAnAction_DoesNotAffectOtherActions()
|
||||
{
|
||||
// Request to an action which does NOT expect form value model binding
|
||||
// Arrange & Act
|
||||
var response = await Client.PostAsync(
|
||||
"http://localhost/ResourceFilter/FormValueModelBinding_Disabled",
|
||||
new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("SampleInt", "10") }));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal("text/plain", response.Content.Headers.ContentType.MediaType);
|
||||
Assert.Equal("Data:0", await response.Content.ReadAsStringAsync());
|
||||
|
||||
// Request to an action which expects form value model binding
|
||||
// Arrange & Act
|
||||
response = await Client.PostAsync(
|
||||
"http://localhost/ResourceFilter/FormValueModelBinding_Enabled",
|
||||
new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("SampleInt", "10") }));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal("text/plain", response.Content.Headers.ContentType.MediaType);
|
||||
Assert.Equal("Data:10", await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. 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.AspNetCore.Diagnostics;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -43,7 +45,8 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
{
|
||||
return new ResourceExecutingContext(
|
||||
CreateActionContext(),
|
||||
filters);
|
||||
filters,
|
||||
new List<IValueProviderFactory>());
|
||||
}
|
||||
|
||||
private static ActionContext CreateActionContext()
|
||||
|
|
|
|||
|
|
@ -28,6 +28,29 @@ namespace FiltersWebSite.Controllers
|
|||
return "NeverGetsExecuted";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult FormValueModelBinding_Enabled(DummyClass dc)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
return Ok("Data:" + dc?.SampleInt);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[DisableFormValueModelBinding]
|
||||
public IActionResult FormValueModelBinding_Disabled(DummyClass dc)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
return Ok("Data:" + dc?.SampleInt);
|
||||
}
|
||||
|
||||
private class ShortCircuitWithFormatterAttribute : Attribute, IResourceFilter
|
||||
{
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) .NET Foundation. 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.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace FiltersWebSite
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
|
||||
{
|
||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||
{
|
||||
var formValueProviderFactory = context.ValueProviderFactories
|
||||
.OfType<FormValueProviderFactory>()
|
||||
.FirstOrDefault();
|
||||
if (formValueProviderFactory != null)
|
||||
{
|
||||
context.ValueProviderFactories.Remove(formValueProviderFactory);
|
||||
}
|
||||
|
||||
var jqueryFormValueProviderFactory = context.ValueProviderFactories
|
||||
.OfType<JQueryFormValueProviderFactory>()
|
||||
.FirstOrDefault();
|
||||
if (jqueryFormValueProviderFactory != null)
|
||||
{
|
||||
context.ValueProviderFactories.Remove(jqueryFormValueProviderFactory);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue