From 8682fe0cfd48fba29aae4bc96440c0140e164ec5 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Wed, 11 Nov 2015 09:36:03 -0800 Subject: [PATCH] Replace ActionBindingContext with ControllerContext This change introduces ControllerContext for inside of Controllers, and controller-specific extensibility points. ControllerContext carries with it the model binding infrastructure needed to do all of the things that controllers need to do. --- Mvc.NoFun.sln | 2 +- samples/MvcSample.Web/HomeController.cs | 2 +- samples/MvcSample.Web/SimpleRest.cs | 2 +- .../Filters/ResourceExecutingContext.cs | 5 - .../ModelBinding/IValueProviderFactory.cs | 4 +- .../ValueProviderFactoryContext.cs | 34 --- .../ActionBindingContext.cs | 23 -- .../ControllerContext.cs | 159 ++++++++++++++ ...ibute.cs => ControllerContextAttribute.cs} | 4 +- .../Controllers/ControllerActionInvoker.cs | 35 +-- .../ControllerActionInvokerProvider.cs | 8 - .../DefaultControllerActionArgumentBinder.cs | 49 ++--- .../Controllers/DefaultControllerFactory.cs | 25 ++- .../DefaultControllerPropertyActivator.cs | 41 ++-- .../Controllers/FilterActionInvoker.cs | 93 +++----- .../IControllerActionArgumentBinder.cs | 10 +- .../Controllers/IControllerFactory.cs | 6 +- .../IControllerPropertyActivator.cs | 2 +- .../MvcCoreServiceCollectionExtensions.cs | 1 - .../ActionBindingContextAccessor.cs | 40 ---- .../IActionBindingContextAccessor.cs | 10 - .../Infrastructure/ObjectResultExecutor.cs | 27 +-- .../ModelBinding/CompositeValueProvider.cs | 40 +--- .../ModelBinding/FormValueProviderFactory.cs | 2 +- .../JQueryFormValueProviderFactory.cs | 2 +- .../QueryStringValueProviderFactory.cs | 2 +- .../RouteValueValueProviderFactory.cs | 4 +- src/Microsoft.AspNet.Mvc.Core/ObjectResult.cs | 4 +- .../Controller.cs | 181 +++++----------- ...taDictionaryControllerPropertyActivator.cs | 16 +- .../ApiController.cs | 41 +++- .../ControllerActionArgumentBinderTests.cs | 180 ++++++---------- .../ControllerActionInvokerTest.cs | 14 +- .../DefaultControllerFactoryTest.cs | 128 ++++++----- .../CreatedAtActionResultTests.cs | 1 - .../CreatedAtRouteResultTests.cs | 1 - .../CreatedResultTests.cs | 1 - .../HttpNotFoundObjectResultTest.cs | 1 - .../HttpOkObjectResultTest.cs | 1 - .../DefaultActionSelectorTests.cs | 8 +- .../ObjectResultExecutorTest.cs | 46 +--- .../FormValueProviderFactoryTest.cs | 8 +- .../JQueryFormValueProviderFactoryTest.cs | 10 +- .../QueryStringValueProviderFactoryTest.cs | 9 +- .../ObjectResultTests.cs | 3 +- .../ModelBindingTestHelper.cs | 87 ++++---- ...MutableObjectModelBinderIntegrationTest.cs | 1 + .../ControllerTest.cs | 202 ++++++++---------- .../ControllerUnitTestabilityTests.cs | 56 +++-- .../ApiControllerTest.cs | 11 +- .../BadRequestErrorMessageResultTest.cs | 1 - .../ExceptionResultTest.cs | 1 - .../InvalidModelStateResultTest.cs | 1 - .../NegotiatedContentResultTest.cs | 1 - .../Controllers/ActionModelController.cs | 5 +- .../Controllers/ApplicationModelController.cs | 6 +- .../Controllers/ControllerModelController.cs | 4 +- .../Controllers/HomeController.cs | 7 +- .../Controllers/LisenceController.cs | 4 +- .../Controllers/ParameterModelController.cs | 2 +- .../Controllers/HomeController.cs | 3 +- .../Controllers/RoutingController.cs | 4 +- .../SpecificFormattersController.cs | 20 +- .../FallbackOnTypeBasedMatchController.cs | 2 +- .../CustomRoute_OrdersControlller.cs | 2 +- .../Controllers/JsonOnlyController.cs | 21 +- .../Controllers/InputFormatterController.cs | 5 +- .../Controllers/ProductsController.cs | 20 +- .../Controllers/StoreController.cs | 4 +- .../Controllers/HomeController.cs | 4 +- .../Controllers/RoundtripController.cs | 2 +- .../CustomValueProviderFactory.cs | 3 +- 72 files changed, 730 insertions(+), 1034 deletions(-) delete mode 100644 src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/ValueProviderFactoryContext.cs delete mode 100644 src/Microsoft.AspNet.Mvc.Core/ActionBindingContext.cs create mode 100644 src/Microsoft.AspNet.Mvc.Core/ControllerContext.cs rename src/Microsoft.AspNet.Mvc.Core/{ActionBindingContextAttribute.cs => ControllerContextAttribute.cs} (73%) delete mode 100644 src/Microsoft.AspNet.Mvc.Core/Infrastructure/ActionBindingContextAccessor.cs delete mode 100644 src/Microsoft.AspNet.Mvc.Core/Infrastructure/IActionBindingContextAccessor.cs diff --git a/Mvc.NoFun.sln b/Mvc.NoFun.sln index 71040b9d55..3d29a9003e 100644 --- a/Mvc.NoFun.sln +++ b/Mvc.NoFun.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +VisualStudioVersion = 14.0.24711.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}" EndProject diff --git a/samples/MvcSample.Web/HomeController.cs b/samples/MvcSample.Web/HomeController.cs index 6b801df75d..d7ffea4664 100644 --- a/samples/MvcSample.Web/HomeController.cs +++ b/samples/MvcSample.Web/HomeController.cs @@ -58,7 +58,7 @@ namespace MvcSample.Web public bool IsDefaultNameSpace() { - var namespaceToken = ActionContext.RouteData.DataTokens["NameSpace"] as string; + var namespaceToken = RouteData.DataTokens["NameSpace"] as string; return namespaceToken == "default"; } diff --git a/samples/MvcSample.Web/SimpleRest.cs b/samples/MvcSample.Web/SimpleRest.cs index 890c18c2fe..514f0d0763 100644 --- a/samples/MvcSample.Web/SimpleRest.cs +++ b/samples/MvcSample.Web/SimpleRest.cs @@ -19,7 +19,7 @@ namespace MvcSample.Web public string GetOtherThing() { // Will be GetOtherThing - return (string)ActionContext.RouteData.Values["action"]; + return (string)RouteData.Values["action"]; } [HttpGet("Link")] diff --git a/src/Microsoft.AspNet.Mvc.Abstractions/Filters/ResourceExecutingContext.cs b/src/Microsoft.AspNet.Mvc.Abstractions/Filters/ResourceExecutingContext.cs index f35aab6d79..ad0a0599ff 100644 --- a/src/Microsoft.AspNet.Mvc.Abstractions/Filters/ResourceExecutingContext.cs +++ b/src/Microsoft.AspNet.Mvc.Abstractions/Filters/ResourceExecutingContext.cs @@ -29,11 +29,6 @@ namespace Microsoft.AspNet.Mvc.Filters /// public virtual FormatterCollection InputFormatters { get; set; } - /// - /// Gets or sets the list of instances used to format the response. - /// - public virtual FormatterCollection OutputFormatters { get; set; } - /// /// Gets or sets the list of instances used by model binding. /// diff --git a/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/IValueProviderFactory.cs b/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/IValueProviderFactory.cs index 66b8876c39..08b05f1599 100644 --- a/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/IValueProviderFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/IValueProviderFactory.cs @@ -10,10 +10,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding /// /// Gets a with values from the current request. /// - /// The . + /// The . /// /// A that when completed will yield a instance or null. /// - Task GetValueProviderAsync(ValueProviderFactoryContext context); + Task GetValueProviderAsync(ActionContext context); } } diff --git a/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/ValueProviderFactoryContext.cs b/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/ValueProviderFactoryContext.cs deleted file mode 100644 index d06b0469e8..0000000000 --- a/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/ValueProviderFactoryContext.cs +++ /dev/null @@ -1,34 +0,0 @@ -// 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.AspNet.Http; - -namespace Microsoft.AspNet.Mvc.ModelBinding -{ - public class ValueProviderFactoryContext - { - public ValueProviderFactoryContext( - HttpContext httpContext, - IDictionary routeValues) - { - if (httpContext == null) - { - throw new ArgumentNullException(nameof(httpContext)); - } - - if (routeValues == null) - { - throw new ArgumentNullException(nameof(routeValues)); - } - - HttpContext = httpContext; - RouteValues = routeValues; - } - - public HttpContext HttpContext { get; private set; } - - public IDictionary RouteValues { get; private set; } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionBindingContext.cs b/src/Microsoft.AspNet.Mvc.Core/ActionBindingContext.cs deleted file mode 100644 index 122236af8d..0000000000 --- a/src/Microsoft.AspNet.Mvc.Core/ActionBindingContext.cs +++ /dev/null @@ -1,23 +0,0 @@ -// 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.AspNet.Mvc.Formatters; -using Microsoft.AspNet.Mvc.ModelBinding; -using Microsoft.AspNet.Mvc.ModelBinding.Validation; - -namespace Microsoft.AspNet.Mvc -{ - public class ActionBindingContext - { - public IModelBinder ModelBinder { get; set; } - - public IValueProvider ValueProvider { get; set; } - - public IList InputFormatters { get; set; } - - public IList OutputFormatters { get; set; } - - public IModelValidatorProvider ValidatorProvider { get; set; } - } -} diff --git a/src/Microsoft.AspNet.Mvc.Core/ControllerContext.cs b/src/Microsoft.AspNet.Mvc.Core/ControllerContext.cs new file mode 100644 index 0000000000..7ed7f6cf99 --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Core/ControllerContext.cs @@ -0,0 +1,159 @@ +// 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.AspNet.Mvc.Controllers; +using Microsoft.AspNet.Mvc.Core; +using Microsoft.AspNet.Mvc.Formatters; +using Microsoft.AspNet.Mvc.ModelBinding; +using Microsoft.AspNet.Mvc.ModelBinding.Validation; + +namespace Microsoft.AspNet.Mvc +{ + /// + /// The context associated with the current request for a controller. + /// + public class ControllerContext : ActionContext + { + private FormatterCollection _inputFormatters; + private IList _modelBinders; + private IList _validatorProviders; + private IList _valueProviders; + + /// + /// Creates a new . + /// + /// + /// The default constructor is provided for unit test purposes only. + /// + public ControllerContext() + : base() + { + } + + /// + /// Creates a new . + /// + /// The associated with the current request. + public ControllerContext(ActionContext context) + : base(context) + { + if (!(context.ActionDescriptor is ControllerActionDescriptor)) + { + throw new ArgumentException(Resources.FormatActionDescriptorMustBeBasedOnControllerAction( + typeof(ControllerActionDescriptor)), + nameof(context)); + } + } + + /// + /// Gets or sets the associated with the current request. + /// + public new ControllerActionDescriptor ActionDescriptor + { + get { return (ControllerActionDescriptor)base.ActionDescriptor; } + set { base.ActionDescriptor = value; } + } + + /// + /// Gets or sets the list of instances for the current request. + /// + public virtual FormatterCollection InputFormatters + { + get + { + if (_inputFormatters == null) + { + _inputFormatters = new FormatterCollection(); + } + + return _inputFormatters; + } + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + _inputFormatters = value; + } + } + + /// + /// Gets or sets the list of instances for the current request. + /// + public virtual IList ModelBinders + { + get + { + if (_modelBinders == null) + { + _modelBinders = new List(); + } + + return _modelBinders; + } + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + _modelBinders = value; + } + } + + /// + /// Gets or sets the list of instances for the current request. + /// + public virtual IList ValidatorProviders + { + get + { + if (_validatorProviders == null) + { + _validatorProviders = new List(); + } + + return _validatorProviders; + } + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + _validatorProviders = value; + } + } + + /// + /// Gets or sets the list of instances for the current request. + /// + public virtual IList ValueProviders + { + get + { + if (_valueProviders == null) + { + _valueProviders = new List(); + } + + return _valueProviders; + } + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + _valueProviders = value; + } + } + } +} diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionBindingContextAttribute.cs b/src/Microsoft.AspNet.Mvc.Core/ControllerContextAttribute.cs similarity index 73% rename from src/Microsoft.AspNet.Mvc.Core/ActionBindingContextAttribute.cs rename to src/Microsoft.AspNet.Mvc.Core/ControllerContextAttribute.cs index 72bf1dd423..1bbce442f6 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionBindingContextAttribute.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ControllerContextAttribute.cs @@ -7,11 +7,11 @@ namespace Microsoft.AspNet.Mvc { /// /// Specifies that a controller property should be set with the current - /// when creating the controller. The property must have a public + /// when creating the controller. The property must have a public /// set method. /// [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] - public class ActionBindingContextAttribute : Attribute + public class ControllerContextAttribute : Attribute { } } diff --git a/src/Microsoft.AspNet.Mvc.Core/Controllers/ControllerActionInvoker.cs b/src/Microsoft.AspNet.Mvc.Core/Controllers/ControllerActionInvoker.cs index a423dddeac..3b30cde785 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Controllers/ControllerActionInvoker.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Controllers/ControllerActionInvoker.cs @@ -9,7 +9,6 @@ using System.Threading.Tasks; using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Filters; using Microsoft.AspNet.Mvc.Formatters; -using Microsoft.AspNet.Mvc.Infrastructure; using Microsoft.AspNet.Mvc.Logging; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding.Validation; @@ -30,12 +29,10 @@ namespace Microsoft.AspNet.Mvc.Controllers IControllerFactory controllerFactory, ControllerActionDescriptor descriptor, IReadOnlyList inputFormatters, - IReadOnlyList outputFormatters, IControllerActionArgumentBinder controllerActionArgumentBinder, IReadOnlyList modelBinders, IReadOnlyList modelValidatorProviders, IReadOnlyList valueProviderFactories, - IActionBindingContextAccessor actionBindingContextAccessor, ILogger logger, DiagnosticSource diagnosticSource, int maxModelValidationErrors) @@ -43,11 +40,9 @@ namespace Microsoft.AspNet.Mvc.Controllers actionContext, filterProviders, inputFormatters, - outputFormatters, modelBinders, modelValidatorProviders, valueProviderFactories, - actionBindingContextAccessor, logger, diagnosticSource, maxModelValidationErrors) @@ -77,11 +72,6 @@ namespace Microsoft.AspNet.Mvc.Controllers throw new ArgumentNullException(nameof(inputFormatters)); } - if (outputFormatters == null) - { - throw new ArgumentNullException(nameof(outputFormatters)); - } - if (controllerActionArgumentBinder == null) { throw new ArgumentNullException(nameof(controllerActionArgumentBinder)); @@ -102,11 +92,6 @@ namespace Microsoft.AspNet.Mvc.Controllers throw new ArgumentNullException(nameof(valueProviderFactories)); } - if (actionBindingContextAccessor == null) - { - throw new ArgumentNullException(nameof(actionBindingContextAccessor)); - } - if (logger == null) { throw new ArgumentNullException(nameof(logger)); @@ -132,9 +117,7 @@ namespace Microsoft.AspNet.Mvc.Controllers protected override object CreateInstance() { - // The binding context is used in activation - Debug.Assert(ActionBindingContext != null); - return _controllerFactory.CreateController(ActionContext); + return _controllerFactory.CreateController(Context); } protected override void ReleaseInstance(object instance) @@ -165,21 +148,9 @@ namespace Microsoft.AspNet.Mvc.Controllers return actionResult; } - protected override Task> BindActionArgumentsAsync( - ActionContext context, - ActionBindingContext bindingContext) + protected override Task> BindActionArgumentsAsync() { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (bindingContext == null) - { - throw new ArgumentNullException(nameof(bindingContext)); - } - - return _argumentBinder.BindActionArgumentsAsync(context, bindingContext, Instance); + return _argumentBinder.BindActionArgumentsAsync(Context, Instance); } // Marking as internal for Unit Testing purposes. diff --git a/src/Microsoft.AspNet.Mvc.Core/Controllers/ControllerActionInvokerProvider.cs b/src/Microsoft.AspNet.Mvc.Core/Controllers/ControllerActionInvokerProvider.cs index 2218afad0a..166f7198cd 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Controllers/ControllerActionInvokerProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Controllers/ControllerActionInvokerProvider.cs @@ -8,7 +8,6 @@ using System.Linq; using Microsoft.AspNet.Mvc.Abstractions; using Microsoft.AspNet.Mvc.Filters; using Microsoft.AspNet.Mvc.Formatters; -using Microsoft.AspNet.Mvc.Infrastructure; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding.Validation; using Microsoft.Extensions.Logging; @@ -23,10 +22,8 @@ namespace Microsoft.AspNet.Mvc.Controllers private readonly IFilterProvider[] _filterProviders; private readonly IReadOnlyList _inputFormatters; private readonly IReadOnlyList _modelBinders; - private readonly IReadOnlyList _outputFormatters; private readonly IReadOnlyList _modelValidatorProviders; private readonly IReadOnlyList _valueProviderFactories; - private readonly IActionBindingContextAccessor _actionBindingContextAccessor; private readonly int _maxModelValidationErrors; private readonly ILogger _logger; private readonly DiagnosticSource _diagnosticSource; @@ -36,7 +33,6 @@ namespace Microsoft.AspNet.Mvc.Controllers IEnumerable filterProviders, IControllerActionArgumentBinder argumentBinder, IOptions optionsAccessor, - IActionBindingContextAccessor actionBindingContextAccessor, ILoggerFactory loggerFactory, DiagnosticSource diagnosticSource) { @@ -44,11 +40,9 @@ namespace Microsoft.AspNet.Mvc.Controllers _filterProviders = filterProviders.OrderBy(item => item.Order).ToArray(); _argumentBinder = argumentBinder; _inputFormatters = optionsAccessor.Value.InputFormatters.ToArray(); - _outputFormatters = optionsAccessor.Value.OutputFormatters.ToArray(); _modelBinders = optionsAccessor.Value.ModelBinders.ToArray(); _modelValidatorProviders = optionsAccessor.Value.ModelValidatorProviders.ToArray(); _valueProviderFactories = optionsAccessor.Value.ValueProviderFactories.ToArray(); - _actionBindingContextAccessor = actionBindingContextAccessor; _maxModelValidationErrors = optionsAccessor.Value.MaxModelValidationErrors; _logger = loggerFactory.CreateLogger(); _diagnosticSource = diagnosticSource; @@ -77,12 +71,10 @@ namespace Microsoft.AspNet.Mvc.Controllers _controllerFactory, actionDescriptor, _inputFormatters, - _outputFormatters, _argumentBinder, _modelBinders, _modelValidatorProviders, _valueProviderFactories, - _actionBindingContextAccessor, _logger, _diagnosticSource, _maxModelValidationErrors); diff --git a/src/Microsoft.AspNet.Mvc.Core/Controllers/DefaultControllerActionArgumentBinder.cs b/src/Microsoft.AspNet.Mvc.Core/Controllers/DefaultControllerActionArgumentBinder.cs index 5e3ed7a8ee..ba66374993 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Controllers/DefaultControllerActionArgumentBinder.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Controllers/DefaultControllerActionArgumentBinder.cs @@ -36,18 +36,12 @@ namespace Microsoft.AspNet.Mvc.Controllers } public Task> BindActionArgumentsAsync( - ActionContext actionContext, - ActionBindingContext actionBindingContext, + ControllerContext context, object controller) { - if (actionContext == null) + if (context == null) { - throw new ArgumentNullException(nameof(actionContext)); - } - - if (actionBindingContext == null) - { - throw new ArgumentNullException(nameof(actionBindingContext)); + throw new ArgumentNullException(nameof(context)); } if (controller == null) @@ -55,16 +49,15 @@ namespace Microsoft.AspNet.Mvc.Controllers throw new ArgumentNullException(nameof(controller)); } - var actionDescriptor = actionContext.ActionDescriptor as ControllerActionDescriptor; - if (actionDescriptor == null) + if (context.ActionDescriptor == null) { - throw new ArgumentException( - Resources.FormatActionDescriptorMustBeBasedOnControllerAction( - typeof(ControllerActionDescriptor)), - nameof(actionContext)); + throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull( + nameof(ControllerContext.ActionDescriptor), + nameof(ControllerContext))); } // Perf: Avoid allocating async state machines when we know there's nothing to bind. + var actionDescriptor = context.ActionDescriptor; if (actionDescriptor.BoundProperties.Count == 0 && actionDescriptor.Parameters.Count == 0) { @@ -74,24 +67,22 @@ namespace Microsoft.AspNet.Mvc.Controllers else { return BindActionArgumentsCoreAsync( - actionContext, - actionBindingContext, + context, controller, actionDescriptor); } } private async Task> BindActionArgumentsCoreAsync( - ActionContext actionContext, - ActionBindingContext actionBindingContext, + ControllerContext context, object controller, ControllerActionDescriptor actionDescriptor) { - var operationBindingContext = GetOperationBindingContext(actionContext, actionBindingContext); + var operationBindingContext = GetOperationBindingContext(context); var controllerProperties = new Dictionary(StringComparer.Ordinal); await PopulateArgumentsAsync( operationBindingContext, - actionContext.ModelState, + context.ModelState, controllerProperties, actionDescriptor.BoundProperties); var controllerType = actionDescriptor.ControllerTypeInfo.AsType(); @@ -100,7 +91,7 @@ namespace Microsoft.AspNet.Mvc.Controllers var actionArguments = new Dictionary(StringComparer.Ordinal); await PopulateArgumentsAsync( operationBindingContext, - actionContext.ModelState, + context.ModelState, actionArguments, actionDescriptor.Parameters); return actionArguments; @@ -229,18 +220,16 @@ namespace Microsoft.AspNet.Mvc.Controllers } } - private OperationBindingContext GetOperationBindingContext( - ActionContext actionContext, - ActionBindingContext bindingContext) + private OperationBindingContext GetOperationBindingContext(ControllerContext context) { return new OperationBindingContext { - InputFormatters = bindingContext.InputFormatters, - ModelBinder = bindingContext.ModelBinder, - ValidatorProvider = bindingContext.ValidatorProvider, + InputFormatters = context.InputFormatters, + ModelBinder = new CompositeModelBinder(context.ModelBinders), + ValidatorProvider = new CompositeModelValidatorProvider(context.ValidatorProviders), MetadataProvider = _modelMetadataProvider, - HttpContext = actionContext.HttpContext, - ValueProvider = bindingContext.ValueProvider, + HttpContext = context.HttpContext, + ValueProvider = new CompositeValueProvider(context.ValueProviders), }; } } diff --git a/src/Microsoft.AspNet.Mvc.Core/Controllers/DefaultControllerFactory.cs b/src/Microsoft.AspNet.Mvc.Core/Controllers/DefaultControllerFactory.cs index 0fbd198c8f..685ccfcb11 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Controllers/DefaultControllerFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Controllers/DefaultControllerFactory.cs @@ -47,23 +47,21 @@ namespace Microsoft.AspNet.Mvc.Controllers } /// - public virtual object CreateController(ActionContext actionContext) + public virtual object CreateController(ControllerContext context) { - if (actionContext == null) + if (context == null) { - throw new ArgumentNullException(nameof(actionContext)); + throw new ArgumentNullException(nameof(context)); } - var actionDescriptor = actionContext.ActionDescriptor as ControllerActionDescriptor; - if (actionDescriptor == null) + if (context.ActionDescriptor == null) { - throw new ArgumentException( - Resources.FormatActionDescriptorMustBeBasedOnControllerAction( - typeof(ControllerActionDescriptor)), - nameof(actionContext)); + throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull( + nameof(ControllerContext.ActionDescriptor), + nameof(ControllerContext))); } - var controllerType = actionDescriptor.ControllerTypeInfo.AsType(); + var controllerType = context.ActionDescriptor.ControllerTypeInfo.AsType(); var controllerTypeInfo = controllerType.GetTypeInfo(); if (controllerTypeInfo.IsValueType || controllerTypeInfo.IsInterface || @@ -71,14 +69,15 @@ namespace Microsoft.AspNet.Mvc.Controllers (controllerTypeInfo.IsGenericType && controllerTypeInfo.IsGenericTypeDefinition)) { var message = Resources.FormatValueInterfaceAbstractOrOpenGenericTypesCannotBeActivated( - controllerType.FullName, GetType().FullName); + controllerType.FullName, + GetType().FullName); throw new InvalidOperationException(message); } - var controller = _controllerActivator.Create(actionContext, controllerType); + var controller = _controllerActivator.Create(context, controllerType); foreach (var propertyActivator in _propertyActivators) { - propertyActivator.Activate(actionContext, controller); + propertyActivator.Activate(context, controller); } return controller; diff --git a/src/Microsoft.AspNet.Mvc.Core/Controllers/DefaultControllerPropertyActivator.cs b/src/Microsoft.AspNet.Mvc.Core/Controllers/DefaultControllerPropertyActivator.cs index c984721339..10643342d4 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Controllers/DefaultControllerPropertyActivator.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Controllers/DefaultControllerPropertyActivator.cs @@ -12,58 +12,43 @@ namespace Microsoft.AspNet.Mvc.Controllers { public class DefaultControllerPropertyActivator : IControllerPropertyActivator { - private readonly IActionBindingContextAccessor _actionBindingContextAccessor; - private readonly ConcurrentDictionary[]> _activateActions; - private readonly Func[]> _getPropertiesToActivate; + private readonly ConcurrentDictionary[]> _activateActions; + private readonly Func[]> _getPropertiesToActivate; - public DefaultControllerPropertyActivator(IActionBindingContextAccessor actionBindingContextAccessor) + public DefaultControllerPropertyActivator() { - _actionBindingContextAccessor = actionBindingContextAccessor; - - _activateActions = new ConcurrentDictionary[]>(); + _activateActions = new ConcurrentDictionary[]>(); _getPropertiesToActivate = GetPropertiesToActivate; } - public void Activate(ActionContext actionContext, object controller) + public void Activate(ControllerContext context, object controller) { var controllerType = controller.GetType(); var propertiesToActivate = _activateActions.GetOrAdd( controllerType, _getPropertiesToActivate); - var contexts = new Contexts() - { - ActionBindingContext = _actionBindingContextAccessor.ActionBindingContext, - ActionContext = actionContext, - }; - for (var i = 0; i < propertiesToActivate.Length; i++) { var activateInfo = propertiesToActivate[i]; - activateInfo.Activate(controller, contexts); + activateInfo.Activate(controller, context); } } - private PropertyActivator[] GetPropertiesToActivate(Type type) + private PropertyActivator[] GetPropertiesToActivate(Type type) { - IEnumerable> activators; - activators = PropertyActivator.GetPropertiesToActivate( + IEnumerable> activators; + activators = PropertyActivator.GetPropertiesToActivate( type, typeof(ActionContextAttribute), - p => new PropertyActivator(p, c => c.ActionContext)); + p => new PropertyActivator(p, c => c)); - activators = activators.Concat(PropertyActivator.GetPropertiesToActivate( + activators = activators.Concat(PropertyActivator.GetPropertiesToActivate( type, - typeof(ActionBindingContextAttribute), - p => new PropertyActivator(p, c => c.ActionBindingContext))); + typeof(ControllerContextAttribute), + p => new PropertyActivator(p, c => c))); return activators.ToArray(); } - - private struct Contexts - { - public ActionBindingContext ActionBindingContext; - public ActionContext ActionContext; - } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/Controllers/FilterActionInvoker.cs b/src/Microsoft.AspNet.Mvc.Core/Controllers/FilterActionInvoker.cs index 27a1e40d7c..a26d914b9a 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Controllers/FilterActionInvoker.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Controllers/FilterActionInvoker.cs @@ -11,7 +11,6 @@ using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Diagnostics; using Microsoft.AspNet.Mvc.Filters; using Microsoft.AspNet.Mvc.Formatters; -using Microsoft.AspNet.Mvc.Infrastructure; using Microsoft.AspNet.Mvc.Internal; using Microsoft.AspNet.Mvc.Logging; using Microsoft.AspNet.Mvc.ModelBinding; @@ -27,10 +26,8 @@ namespace Microsoft.AspNet.Mvc.Controllers private readonly IReadOnlyList _filterProviders; private readonly IReadOnlyList _inputFormatters; private readonly IReadOnlyList _modelBinders; - private readonly IReadOnlyList _outputFormatters; private readonly IReadOnlyList _modelValidatorProviders; private readonly IReadOnlyList _valueProviderFactories; - private readonly IActionBindingContextAccessor _actionBindingContextAccessor; private readonly DiagnosticSource _diagnosticSource; private readonly int _maxModelValidationErrors; @@ -54,11 +51,9 @@ namespace Microsoft.AspNet.Mvc.Controllers ActionContext actionContext, IReadOnlyList filterProviders, IReadOnlyList inputFormatters, - IReadOnlyList outputFormatters, IReadOnlyList modelBinders, IReadOnlyList modelValidatorProviders, IReadOnlyList valueProviderFactories, - IActionBindingContextAccessor actionBindingContextAccessor, ILogger logger, DiagnosticSource diagnosticSource, int maxModelValidationErrors) @@ -78,11 +73,6 @@ namespace Microsoft.AspNet.Mvc.Controllers throw new ArgumentNullException(nameof(inputFormatters)); } - if (outputFormatters == null) - { - throw new ArgumentNullException(nameof(outputFormatters)); - } - if (modelBinders == null) { throw new ArgumentNullException(nameof(modelBinders)); @@ -98,11 +88,6 @@ namespace Microsoft.AspNet.Mvc.Controllers throw new ArgumentNullException(nameof(valueProviderFactories)); } - if (actionBindingContextAccessor == null) - { - throw new ArgumentNullException(nameof(actionBindingContextAccessor)); - } - if (logger == null) { throw new ArgumentNullException(nameof(logger)); @@ -113,33 +98,19 @@ namespace Microsoft.AspNet.Mvc.Controllers throw new ArgumentNullException(nameof(diagnosticSource)); } - ActionContext = actionContext; + Context = new ControllerContext(actionContext); _filterProviders = filterProviders; _inputFormatters = inputFormatters; - _outputFormatters = outputFormatters; _modelBinders = modelBinders; _modelValidatorProviders = modelValidatorProviders; _valueProviderFactories = valueProviderFactories; - _actionBindingContextAccessor = actionBindingContextAccessor; Logger = logger; _diagnosticSource = diagnosticSource; _maxModelValidationErrors = maxModelValidationErrors; } - protected ActionContext ActionContext { get; private set; } - - protected ActionBindingContext ActionBindingContext - { - get - { - return _actionBindingContextAccessor.ActionBindingContext; - } - private set - { - _actionBindingContextAccessor.ActionBindingContext = value; - } - } + protected ControllerContext Context { get; } protected object Instance { get; private set; } @@ -160,16 +131,14 @@ namespace Microsoft.AspNet.Mvc.Controllers protected abstract Task InvokeActionAsync(ActionExecutingContext actionExecutingContext); - protected abstract Task> BindActionArgumentsAsync( - ActionContext context, - ActionBindingContext bindingContext); + protected abstract Task> BindActionArgumentsAsync(); public virtual async Task InvokeAsync() { _filters = GetFilters(); _cursor = new FilterCursor(_filters); - ActionContext.ModelState.MaxAllowedErrors = _maxModelValidationErrors; + Context.ModelState.MaxAllowedErrors = _maxModelValidationErrors; await InvokeAllAuthorizationFiltersAsync(); @@ -215,14 +184,14 @@ namespace Microsoft.AspNet.Mvc.Controllers private IFilterMetadata[] GetFilters() { - var filterDescriptors = ActionContext.ActionDescriptor.FilterDescriptors; + var filterDescriptors = Context.ActionDescriptor.FilterDescriptors; var items = new List(filterDescriptors.Count); for (var i = 0; i < filterDescriptors.Count; i++) { items.Add(new FilterItem(filterDescriptors[i])); } - var context = new FilterProviderContext(ActionContext, items); + var context = new FilterProviderContext(Context, items); for (var i = 0; i < _filterProviders.Count; i++) { _filterProviders[i].OnProvidersExecuting(context); @@ -266,7 +235,7 @@ namespace Microsoft.AspNet.Mvc.Controllers { _cursor.Reset(); - _authorizationContext = new AuthorizationContext(ActionContext, _filters); + _authorizationContext = new AuthorizationContext(Context, _filters); return InvokeAuthorizationFilterAsync(); } @@ -332,12 +301,10 @@ namespace Microsoft.AspNet.Mvc.Controllers { _cursor.Reset(); - var context = new ResourceExecutingContext(ActionContext, _filters); + var context = new ResourceExecutingContext(Context, _filters); context.InputFormatters = new FormatterCollection( new CopyOnWriteList(_inputFormatters)); - context.OutputFormatters = new FormatterCollection( - new CopyOnWriteList(_outputFormatters)); context.ModelBinders = new CopyOnWriteList(_modelBinders); context.ValidatorProviders = new CopyOnWriteList(_modelValidatorProviders); context.ValueProviderFactories = new CopyOnWriteList(_valueProviderFactories); @@ -441,20 +408,22 @@ namespace Microsoft.AspNet.Mvc.Controllers { // We've reached the end of resource filters, so move to setting up state to invoke model // binding. - ActionBindingContext = new ActionBindingContext(); - ActionBindingContext.InputFormatters = _resourceExecutingContext.InputFormatters; - ActionBindingContext.OutputFormatters = _resourceExecutingContext.OutputFormatters; - ActionBindingContext.ModelBinder = new CompositeModelBinder(_resourceExecutingContext.ModelBinders); - ActionBindingContext.ValidatorProvider = new CompositeModelValidatorProvider( - _resourceExecutingContext.ValidatorProviders); + Context.InputFormatters = _resourceExecutingContext.InputFormatters; + Context.ModelBinders = _resourceExecutingContext.ModelBinders; + Context.ValidatorProviders = _resourceExecutingContext.ValidatorProviders; - var valueProviderFactoryContext = new ValueProviderFactoryContext( - ActionContext.HttpContext, - ActionContext.RouteData.Values); + var valueProviders = new List(); - ActionBindingContext.ValueProvider = await CompositeValueProvider.CreateAsync( - _resourceExecutingContext.ValueProviderFactories, - valueProviderFactoryContext); + for (var i = 0; i < _resourceExecutingContext.ValueProviderFactories.Count; i++) + { + var factory = _resourceExecutingContext.ValueProviderFactories[i]; + var valueProvider = await factory.GetValueProviderAsync(Context); + if (valueProvider != null) + { + valueProviders.Add(valueProvider); + } + } + Context.ValueProviders = valueProviders; // >> ExceptionFilters >> Model Binding >> ActionFilters >> Action await InvokeAllExceptionFiltersAsync(); @@ -587,7 +556,7 @@ namespace Microsoft.AspNet.Mvc.Controllers // 1) Call the filter (if we have an exception) // 2) No-op (if we don't have an exception) Debug.Assert(_exceptionContext == null); - _exceptionContext = new ExceptionContext(ActionContext, _filters); + _exceptionContext = new ExceptionContext(Context, _filters); try { @@ -617,10 +586,10 @@ namespace Microsoft.AspNet.Mvc.Controllers Instance = CreateInstance(); - var arguments = await BindActionArgumentsAsync(ActionContext, ActionBindingContext); + var arguments = await BindActionArgumentsAsync(); _actionExecutingContext = new ActionExecutingContext( - ActionContext, + Context, _filters, arguments, Instance); @@ -723,7 +692,7 @@ namespace Microsoft.AspNet.Mvc.Controllers try { _diagnosticSource.BeforeActionMethod( - ActionContext, + Context, _actionExecutingContext.ActionArguments, _actionExecutingContext.Controller); @@ -732,7 +701,7 @@ namespace Microsoft.AspNet.Mvc.Controllers finally { _diagnosticSource.AfterActionMethod( - ActionContext, + Context, _actionExecutingContext.ActionArguments, _actionExecutingContext.Controller, result); @@ -765,7 +734,7 @@ namespace Microsoft.AspNet.Mvc.Controllers { _cursor.Reset(); - _resultExecutingContext = new ResultExecutingContext(ActionContext, _filters, result, Instance); + _resultExecutingContext = new ResultExecutingContext(Context, _filters, result, Instance); await InvokeResultFilterAsync(); Debug.Assert(_resultExecutingContext != null); @@ -908,15 +877,15 @@ namespace Microsoft.AspNet.Mvc.Controllers private async Task InvokeResultAsync(IActionResult result) { - _diagnosticSource.BeforeActionResult(ActionContext, result); + _diagnosticSource.BeforeActionResult(Context, result); try { - await result.ExecuteResultAsync(ActionContext); + await result.ExecuteResultAsync(Context); } finally { - _diagnosticSource.AfterActionResult(ActionContext, result); + _diagnosticSource.AfterActionResult(Context, result); } } diff --git a/src/Microsoft.AspNet.Mvc.Core/Controllers/IControllerActionArgumentBinder.cs b/src/Microsoft.AspNet.Mvc.Core/Controllers/IControllerActionArgumentBinder.cs index 081c0d3377..815c068df2 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Controllers/IControllerActionArgumentBinder.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Controllers/IControllerActionArgumentBinder.cs @@ -12,16 +12,12 @@ namespace Microsoft.AspNet.Mvc.Controllers public interface IControllerActionArgumentBinder { /// - /// Returns a dictionary of representing the parameter-argument name-value pairs, + /// Returns a dictionary of the parameter-argument name-value pairs, /// which can be used to invoke the action. Also binds properties explicitly marked properties on the /// . /// - /// The action context assoicated with the current action. - /// The . + /// The associated with the current action. /// The controller object which contains the action. - Task> BindActionArgumentsAsync( - ActionContext context, - ActionBindingContext bindingContext, - object controller); + Task> BindActionArgumentsAsync(ControllerContext context, object controller); } } diff --git a/src/Microsoft.AspNet.Mvc.Core/Controllers/IControllerFactory.cs b/src/Microsoft.AspNet.Mvc.Core/Controllers/IControllerFactory.cs index 89ad66a14d..5d43c97c54 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Controllers/IControllerFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Controllers/IControllerFactory.cs @@ -9,11 +9,11 @@ namespace Microsoft.AspNet.Mvc.Controllers public interface IControllerFactory { /// - /// Creates a new controller for the specified . + /// Creates a new controller for the specified . /// - /// for the action to execute. + /// for the action to execute. /// The controller. - object CreateController(ActionContext actionContext); + object CreateController(ControllerContext context); /// /// Releases a controller instance. diff --git a/src/Microsoft.AspNet.Mvc.Core/Controllers/IControllerPropertyActivator.cs b/src/Microsoft.AspNet.Mvc.Core/Controllers/IControllerPropertyActivator.cs index ab9a1a4446..e14ee0095d 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Controllers/IControllerPropertyActivator.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Controllers/IControllerPropertyActivator.cs @@ -5,6 +5,6 @@ namespace Microsoft.AspNet.Mvc.Controllers { public interface IControllerPropertyActivator { - void Activate(ActionContext actionContext, object controller); + void Activate(ControllerContext context, object controller); } } diff --git a/src/Microsoft.AspNet.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs b/src/Microsoft.AspNet.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs index d40520b185..02c75ec814 100644 --- a/src/Microsoft.AspNet.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNet.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs @@ -139,7 +139,6 @@ namespace Microsoft.Extensions.DependencyInjection services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); - services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); diff --git a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/ActionBindingContextAccessor.cs b/src/Microsoft.AspNet.Mvc.Core/Infrastructure/ActionBindingContextAccessor.cs deleted file mode 100644 index 345edf237b..0000000000 --- a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/ActionBindingContextAccessor.cs +++ /dev/null @@ -1,40 +0,0 @@ -// 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. - -#if NET451 -using System.Runtime.Remoting; -using System.Runtime.Remoting.Messaging; -#else -using System.Threading; -#endif - -namespace Microsoft.AspNet.Mvc.Infrastructure -{ - public class ActionBindingContextAccessor : IActionBindingContextAccessor - { -#if NET451 - private static string Key = typeof(ActionBindingContext).FullName; - - public ActionBindingContext ActionBindingContext - { - get - { - var handle = CallContext.LogicalGetData(Key) as ObjectHandle; - return handle != null ? (ActionBindingContext)handle.Unwrap() : null; - } - set - { - CallContext.LogicalSetData(Key, new ObjectHandle(value)); - } - } -#else - private readonly AsyncLocal _storage = new AsyncLocal(); - - public ActionBindingContext ActionBindingContext - { - get { return _storage.Value; } - set { _storage.Value = value; } - } -#endif - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/IActionBindingContextAccessor.cs b/src/Microsoft.AspNet.Mvc.Core/Infrastructure/IActionBindingContextAccessor.cs deleted file mode 100644 index e2e9d44041..0000000000 --- a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/IActionBindingContextAccessor.cs +++ /dev/null @@ -1,10 +0,0 @@ -// 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. - -namespace Microsoft.AspNet.Mvc.Infrastructure -{ - public interface IActionBindingContextAccessor - { - ActionBindingContext ActionBindingContext { get; set; } - } -} diff --git a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/ObjectResultExecutor.cs b/src/Microsoft.AspNet.Mvc.Core/Infrastructure/ObjectResultExecutor.cs index 8d942fd0d3..074b33b00d 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/ObjectResultExecutor.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Infrastructure/ObjectResultExecutor.cs @@ -22,17 +22,14 @@ namespace Microsoft.AspNet.Mvc.Infrastructure /// public class ObjectResultExecutor { - private readonly IActionBindingContextAccessor _bindingContextAccessor; - /// /// Creates a new . /// /// An accessor to . - /// The . + /// The . /// The . public ObjectResultExecutor( IOptions options, - IActionBindingContextAccessor bindingContextAccessor, IHttpResponseStreamWriterFactory writerFactory, ILoggerFactory loggerFactory) { @@ -41,28 +38,16 @@ namespace Microsoft.AspNet.Mvc.Infrastructure throw new ArgumentNullException(nameof(options)); } - if (bindingContextAccessor == null) - { - throw new ArgumentNullException(nameof(bindingContextAccessor)); - } - if (loggerFactory == null) { throw new ArgumentNullException(nameof(loggerFactory)); } - _bindingContextAccessor = bindingContextAccessor; - OptionsFormatters = options.Value.OutputFormatters; RespectBrowserAcceptHeader = options.Value.RespectBrowserAcceptHeader; Logger = loggerFactory.CreateLogger(); WriterFactory = writerFactory.CreateWriter; } - - /// - /// Gets the for the current request. - /// - protected ActionBindingContext BindingContext => _bindingContextAccessor.ActionBindingContext; /// /// Gets the . @@ -72,7 +57,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure /// /// Gets the list of instances from . /// - protected IList OptionsFormatters { get; } + protected FormatterCollection OptionsFormatters { get; } /// /// Gets the value of . @@ -109,7 +94,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure var formatters = result.Formatters; if (formatters == null || formatters.Count == 0) { - formatters = GetDefaultFormatters(); + formatters = OptionsFormatters; } var objectType = result.DeclaredType; @@ -506,11 +491,5 @@ namespace Microsoft.AspNet.Mvc.Infrastructure } } } - - // This can't be cached, because the BindingContext is per-request. - private IList GetDefaultFormatters() - { - return BindingContext?.OutputFormatters ?? OptionsFormatters; - } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeValueProvider.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeValueProvider.cs index 7c392a094f..493665e0d7 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeValueProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeValueProvider.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using System.Threading.Tasks; namespace Microsoft.AspNet.Mvc.ModelBinding { @@ -30,48 +29,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding /// /// The sequence of to add to this instance of /// . - protected CompositeValueProvider(IList valueProviders) + public CompositeValueProvider(IList valueProviders) : base(valueProviders) { } - /// - /// Creates a new from the provided - /// and . - /// - /// The set of instances. - /// The . - /// - /// A containing all instances - /// created. - /// - public static async Task CreateAsync( - IEnumerable factories, - ValueProviderFactoryContext context) - { - if (factories == null) - { - throw new ArgumentNullException(nameof(factories)); - } - - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var composite = new CompositeValueProvider(); - foreach (var valueProvidersFactory in factories) - { - var valueProvider = await valueProvidersFactory.GetValueProviderAsync(context); - if (valueProvider != null) - { - composite.Add(valueProvider); - } - } - - return composite; - } - /// public virtual bool ContainsPrefix(string prefix) { diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/FormValueProviderFactory.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/FormValueProviderFactory.cs index 531b9c5c85..9abc60e999 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/FormValueProviderFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/FormValueProviderFactory.cs @@ -11,7 +11,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding { public class FormValueProviderFactory : IValueProviderFactory { - public Task GetValueProviderAsync(ValueProviderFactoryContext context) + public Task GetValueProviderAsync(ActionContext context) { if (context == null) { diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/JQueryFormValueProviderFactory.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/JQueryFormValueProviderFactory.cs index 49812f6cc5..1c812b5790 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/JQueryFormValueProviderFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/JQueryFormValueProviderFactory.cs @@ -15,7 +15,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding { public class JQueryFormValueProviderFactory : IValueProviderFactory { - public Task GetValueProviderAsync(ValueProviderFactoryContext context) + public Task GetValueProviderAsync(ActionContext context) { if (context == null) { diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/QueryStringValueProviderFactory.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/QueryStringValueProviderFactory.cs index 6538bd0be6..4a18b0f29c 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/QueryStringValueProviderFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/QueryStringValueProviderFactory.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding public class QueryStringValueProviderFactory : IValueProviderFactory { /// - public Task GetValueProviderAsync(ValueProviderFactoryContext context) + public Task GetValueProviderAsync(ActionContext context) { if (context == null) { diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/RouteValueValueProviderFactory.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/RouteValueValueProviderFactory.cs index 74e01682e4..2a0e0c12c5 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/RouteValueValueProviderFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/RouteValueValueProviderFactory.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding { public class RouteValueValueProviderFactory : IValueProviderFactory { - public Task GetValueProviderAsync(ValueProviderFactoryContext context) + public Task GetValueProviderAsync(ActionContext context) { if (context == null) { @@ -17,7 +17,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding return Task.FromResult(new DictionaryBasedValueProvider( BindingSource.Path, - context.RouteValues)); + context.RouteData.Values)); } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/ObjectResult.cs b/src/Microsoft.AspNet.Mvc.Core/ObjectResult.cs index d7b2baaf36..e9f3eb3528 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ObjectResult.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ObjectResult.cs @@ -16,13 +16,13 @@ namespace Microsoft.AspNet.Mvc public ObjectResult(object value) { Value = value; - Formatters = new List(); + Formatters = new FormatterCollection(); ContentTypes = new List(); } public object Value { get; set; } - public IList Formatters { get; set; } + public FormatterCollection Formatters { get; set; } public IList ContentTypes { get; set; } diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/Controller.cs b/src/Microsoft.AspNet.Mvc.ViewFeatures/Controller.cs index ace64731b4..57518191a3 100644 --- a/src/Microsoft.AspNet.Mvc.ViewFeatures/Controller.cs +++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/Controller.cs @@ -27,7 +27,7 @@ namespace Microsoft.AspNet.Mvc /// public abstract class Controller : IActionFilter, IAsyncActionFilter, IDisposable { - private ActionContext _actionContext; + private ControllerContext _controllerContext; private IModelMetadataProvider _metadataProvider; private IObjectModelValidator _objectValidator; private ITempDataDictionary _tempData; @@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Mvc { get { - return ActionContext?.HttpContext?.RequestServices; + return HttpContext?.RequestServices; } } @@ -53,7 +53,7 @@ namespace Microsoft.AspNet.Mvc { get { - return ActionContext?.HttpContext; + return ControllerContext.HttpContext; } } @@ -64,7 +64,7 @@ namespace Microsoft.AspNet.Mvc { get { - return ActionContext?.HttpContext?.Request; + return HttpContext?.Request; } } @@ -75,7 +75,7 @@ namespace Microsoft.AspNet.Mvc { get { - return ActionContext?.HttpContext?.Response; + return HttpContext?.Response; } } @@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Mvc { get { - return ActionContext?.RouteData; + return ControllerContext.RouteData; } } @@ -102,21 +102,24 @@ namespace Microsoft.AspNet.Mvc } /// - /// Gets or sets the object. + /// Gets or sets the . /// /// /// activates this property while activating controllers. - /// If user code directly instantiates a controller, the getter returns an empty - /// . + /// If user code directly instantiates a controller, the getter returns an empty + /// . /// - [ActionContext] - public ActionContext ActionContext + [ControllerContext] + public ControllerContext ControllerContext { get { - // This should run only for the controller unit test scenarios - _actionContext = _actionContext ?? new ActionContext(); - return _actionContext; + if (_controllerContext == null) + { + _controllerContext = new ControllerContext(); + } + + return _controllerContext; } set { @@ -125,16 +128,10 @@ namespace Microsoft.AspNet.Mvc throw new ArgumentNullException(nameof(value)); } - _actionContext = value; + _controllerContext = value; } } - /// - /// Gets or sets the . - /// - [ActionBindingContext] - public ActionBindingContext BindingContext { get; set; } - /// /// Gets or sets the . /// @@ -237,9 +234,7 @@ namespace Microsoft.AspNet.Mvc if (_viewData == null) { // This should run only for the controller unit test scenarios - _viewData = - new ViewDataDictionary(new EmptyModelMetadataProvider(), - ActionContext?.ModelState ?? new ModelStateDictionary()); + _viewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), ControllerContext.ModelState); } return _viewData; @@ -1407,15 +1402,7 @@ namespace Microsoft.AspNet.Mvc throw new ArgumentNullException(nameof(prefix)); } - if (BindingContext == null) - { - var message = Resources.FormatPropertyOfTypeCannotBeNull( - nameof(BindingContext), - typeof(Controller).FullName); - throw new InvalidOperationException(message); - } - - return TryUpdateModelAsync(model, prefix, BindingContext.ValueProvider); + return TryUpdateModelAsync(model, prefix, new CompositeValueProvider(ControllerContext.ValueProviders)); } /// @@ -1450,25 +1437,17 @@ namespace Microsoft.AspNet.Mvc throw new ArgumentNullException(nameof(valueProvider)); } - if (BindingContext == null) - { - var message = Resources.FormatPropertyOfTypeCannotBeNull( - nameof(BindingContext), - typeof(Controller).FullName); - throw new InvalidOperationException(message); - } - return ModelBindingHelper.TryUpdateModelAsync( model, prefix, - ActionContext.HttpContext, + HttpContext, ModelState, MetadataProvider, - BindingContext.ModelBinder, + new CompositeModelBinder(ControllerContext.ModelBinders), valueProvider, - BindingContext.InputFormatters, + ControllerContext.InputFormatters, ObjectValidator, - BindingContext.ValidatorProvider); + new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders)); } /// @@ -1499,25 +1478,17 @@ namespace Microsoft.AspNet.Mvc throw new ArgumentNullException(nameof(includeExpressions)); } - if (BindingContext == null) - { - var message = Resources.FormatPropertyOfTypeCannotBeNull( - nameof(BindingContext), - typeof(Controller).FullName); - throw new InvalidOperationException(message); - } - return ModelBindingHelper.TryUpdateModelAsync( model, prefix, - ActionContext.HttpContext, + HttpContext, ModelState, MetadataProvider, - BindingContext.ModelBinder, - BindingContext.ValueProvider, - BindingContext.InputFormatters, + new CompositeModelBinder(ControllerContext.ModelBinders), + new CompositeValueProvider(ControllerContext.ValueProviders), + ControllerContext.InputFormatters, ObjectValidator, - BindingContext.ValidatorProvider, + new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders), includeExpressions); } @@ -1548,25 +1519,17 @@ namespace Microsoft.AspNet.Mvc throw new ArgumentNullException(nameof(predicate)); } - if (BindingContext == null) - { - var message = Resources.FormatPropertyOfTypeCannotBeNull( - nameof(BindingContext), - typeof(Controller).FullName); - throw new InvalidOperationException(message); - } - return ModelBindingHelper.TryUpdateModelAsync( model, prefix, - ActionContext.HttpContext, + HttpContext, ModelState, MetadataProvider, - BindingContext.ModelBinder, - BindingContext.ValueProvider, - BindingContext.InputFormatters, + new CompositeModelBinder(ControllerContext.ModelBinders), + new CompositeValueProvider(ControllerContext.ValueProviders), + ControllerContext.InputFormatters, ObjectValidator, - BindingContext.ValidatorProvider, + new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders), predicate); } @@ -1605,25 +1568,17 @@ namespace Microsoft.AspNet.Mvc throw new ArgumentNullException(nameof(includeExpressions)); } - if (BindingContext == null) - { - var message = Resources.FormatPropertyOfTypeCannotBeNull( - nameof(BindingContext), - typeof(Controller).FullName); - throw new InvalidOperationException(message); - } - return ModelBindingHelper.TryUpdateModelAsync( model, prefix, - ActionContext.HttpContext, + HttpContext, ModelState, MetadataProvider, - BindingContext.ModelBinder, + new CompositeModelBinder(ControllerContext.ModelBinders), valueProvider, - BindingContext.InputFormatters, + ControllerContext.InputFormatters, ObjectValidator, - BindingContext.ValidatorProvider, + new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders), includeExpressions); } @@ -1661,25 +1616,17 @@ namespace Microsoft.AspNet.Mvc throw new ArgumentNullException(nameof(predicate)); } - if (BindingContext == null) - { - var message = Resources.FormatPropertyOfTypeCannotBeNull( - nameof(BindingContext), - typeof(Controller).FullName); - throw new InvalidOperationException(message); - } - return ModelBindingHelper.TryUpdateModelAsync( model, prefix, - ActionContext.HttpContext, + HttpContext, ModelState, MetadataProvider, - BindingContext.ModelBinder, + new CompositeModelBinder(ControllerContext.ModelBinders), valueProvider, - BindingContext.InputFormatters, + ControllerContext.InputFormatters, ObjectValidator, - BindingContext.ValidatorProvider, + new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders), predicate); } @@ -1708,26 +1655,18 @@ namespace Microsoft.AspNet.Mvc throw new ArgumentNullException(nameof(modelType)); } - if (BindingContext == null) - { - var message = Resources.FormatPropertyOfTypeCannotBeNull( - nameof(BindingContext), - typeof(Controller).FullName); - throw new InvalidOperationException(message); - } - return ModelBindingHelper.TryUpdateModelAsync( model, modelType, prefix, - ActionContext.HttpContext, + HttpContext, ModelState, MetadataProvider, - BindingContext.ModelBinder, - BindingContext.ValueProvider, - BindingContext.InputFormatters, + new CompositeModelBinder(ControllerContext.ModelBinders), + new CompositeValueProvider(ControllerContext.ValueProviders), + ControllerContext.InputFormatters, ObjectValidator, - BindingContext.ValidatorProvider); + new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders)); } /// @@ -1769,26 +1708,18 @@ namespace Microsoft.AspNet.Mvc throw new ArgumentNullException(nameof(predicate)); } - if (BindingContext == null) - { - var message = Resources.FormatPropertyOfTypeCannotBeNull( - nameof(BindingContext), - typeof(Controller).FullName); - throw new InvalidOperationException(message); - } - return ModelBindingHelper.TryUpdateModelAsync( model, modelType, prefix, - ActionContext.HttpContext, + HttpContext, ModelState, MetadataProvider, - BindingContext.ModelBinder, + new CompositeModelBinder(ControllerContext.ModelBinders), valueProvider, - BindingContext.InputFormatters, + ControllerContext.InputFormatters, ObjectValidator, - BindingContext.ValidatorProvider, + new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders), predicate); } @@ -1826,14 +1757,6 @@ namespace Microsoft.AspNet.Mvc throw new ArgumentNullException(nameof(model)); } - if (BindingContext == null) - { - var message = Resources.FormatPropertyOfTypeCannotBeNull( - nameof(BindingContext), - typeof(Controller).FullName); - throw new InvalidOperationException(message); - } - var modelExplorer = MetadataProvider.GetModelExplorerForType(model.GetType(), model); var modelName = prefix ?? string.Empty; @@ -1846,7 +1769,7 @@ namespace Microsoft.AspNet.Mvc modelName); ObjectValidator.Validate( - BindingContext.ValidatorProvider, + new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders), ModelState, validationState: null, prefix: prefix, diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/ViewDataDictionaryControllerPropertyActivator.cs b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/ViewDataDictionaryControllerPropertyActivator.cs index 1ebd483006..1e510ce7e7 100644 --- a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/ViewDataDictionaryControllerPropertyActivator.cs +++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/ViewDataDictionaryControllerPropertyActivator.cs @@ -12,18 +12,18 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures public class ViewDataDictionaryControllerPropertyActivator : IControllerPropertyActivator { private readonly IModelMetadataProvider _modelMetadataProvider; - private readonly ConcurrentDictionary[]> _activateActions; - private readonly Func[]> _getPropertiesToActivate; + private readonly ConcurrentDictionary[]> _activateActions; + private readonly Func[]> _getPropertiesToActivate; public ViewDataDictionaryControllerPropertyActivator(IModelMetadataProvider modelMetadataProvider) { _modelMetadataProvider = modelMetadataProvider; - _activateActions = new ConcurrentDictionary[]>(); + _activateActions = new ConcurrentDictionary[]>(); _getPropertiesToActivate = GetPropertiesToActivate; } - public void Activate(ActionContext actionContext, object controller) + public void Activate(ControllerContext actionContext, object controller) { var controllerType = controller.GetType(); var propertiesToActivate = _activateActions.GetOrAdd( @@ -37,17 +37,17 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures } } - private PropertyActivator[] GetPropertiesToActivate(Type type) + private PropertyActivator[] GetPropertiesToActivate(Type type) { - var activators = PropertyActivator.GetPropertiesToActivate( + var activators = PropertyActivator.GetPropertiesToActivate( type, typeof(ViewDataDictionaryAttribute), - p => new PropertyActivator(p, GetViewDataDictionary)); + p => new PropertyActivator(p, GetViewDataDictionary)); return activators; } - private ViewDataDictionary GetViewDataDictionary(ActionContext context) + private ViewDataDictionary GetViewDataDictionary(ControllerContext context) { var serviceProvider = context.HttpContext.RequestServices; return new ViewDataDictionary( diff --git a/src/Microsoft.AspNet.Mvc.WebApiCompatShim/ApiController.cs b/src/Microsoft.AspNet.Mvc.WebApiCompatShim/ApiController.cs index 3c0bca9f3c..c598713847 100644 --- a/src/Microsoft.AspNet.Mvc.WebApiCompatShim/ApiController.cs +++ b/src/Microsoft.AspNet.Mvc.WebApiCompatShim/ApiController.cs @@ -22,24 +22,43 @@ namespace System.Web.Http [UseWebApiOverloading] public abstract class ApiController : IDisposable { + private ControllerContext _controllerContext; private HttpRequestMessage _request; private IModelMetadataProvider _metadataProvider; private IObjectModelValidator _objectValidator; private IUrlHelper _urlHelper; /// - /// Gets the action context. + /// Gets the . /// - /// The setter is intended for unit testing purposes only. - [ActionContext] - public ActionContext ActionContext { get; set; } + public ActionContext ActionContext => ControllerContext; /// - /// Gets the . + /// Gets or sets the . /// /// The setter is intended for unit testing purposes only. - [ActionBindingContext] - public ActionBindingContext BindingContext { get; set; } + [ControllerContext] + public ControllerContext ControllerContext + { + get + { + if (_controllerContext == null) + { + _controllerContext = new ControllerContext(); + } + + return _controllerContext; + } + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + _controllerContext = value; + } + } /// /// Gets the http context. @@ -48,7 +67,7 @@ namespace System.Web.Http { get { - return ActionContext?.HttpContext; + return ControllerContext.HttpContext; } } @@ -101,7 +120,7 @@ namespace System.Web.Http { get { - return ActionContext?.ModelState; + return ControllerContext.ModelState; } } @@ -115,7 +134,7 @@ namespace System.Web.Http { if (_request == null && ActionContext != null) { - _request = ActionContext.HttpContext.GetHttpRequestMessage(); + _request = ControllerContext.HttpContext.GetHttpRequestMessage(); } return _request; @@ -553,7 +572,7 @@ namespace System.Web.Http { var validatidationState = new ValidationStateDictionary(); ObjectValidator.Validate( - BindingContext.ValidatorProvider, + new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders), ModelState, validatidationState, keyPrefix, diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Controllers/ControllerActionArgumentBinderTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Controllers/ControllerActionArgumentBinderTests.cs index bdf049490c..331a84dde2 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Controllers/ControllerActionArgumentBinderTests.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Controllers/ControllerActionArgumentBinderTests.cs @@ -7,6 +7,7 @@ using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNet.Http.Internal; using Microsoft.AspNet.Mvc.Abstractions; +using Microsoft.AspNet.Mvc.Formatters; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding.Test; using Microsoft.AspNet.Mvc.ModelBinding.Validation; @@ -31,24 +32,21 @@ namespace Microsoft.AspNet.Mvc.Controllers BindingInfo = new BindingInfo(), }); - var actionContext = GetActionContext(actionDescriptor); - var binder = new Mock(); binder .Setup(b => b.BindModelAsync(It.IsAny())) .Returns(ModelBindingResult.NoResultAsync); - var actionBindingContext = new ActionBindingContext() - { - ModelBinder = binder.Object, - ValueProvider = new SimpleValueProvider(), - }; + + var controllerContext = GetControllerContext(actionDescriptor); + controllerContext.ModelBinders.Add(binder.Object); + controllerContext.ValueProviders.Add(new SimpleValueProvider()); var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var argumentBinder = GetArgumentBinder(); // Act var result = await argumentBinder - .BindActionArgumentsAsync(actionContext, actionBindingContext, new TestController()); + .BindActionArgumentsAsync(controllerContext, new TestController()); // Assert Assert.Empty(result); @@ -72,23 +70,16 @@ namespace Microsoft.AspNet.Mvc.Controllers .Setup(b => b.BindModelAsync(It.IsAny())) .Returns(ModelBindingResult.FailedAsync(string.Empty)); - var actionContext = new ActionContext( - new DefaultHttpContext(), - new RouteData(), - actionDescriptor); - - var actionBindingContext = new ActionBindingContext() - { - ModelBinder = binder.Object, - ValueProvider = new SimpleValueProvider(), - }; + var controllerContext = GetControllerContext(actionDescriptor); + controllerContext.ModelBinders.Add(binder.Object); + controllerContext.ValueProviders.Add(new SimpleValueProvider()); var argumentBinder = GetArgumentBinder(); var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); // Act var result = await argumentBinder - .BindActionArgumentsAsync(actionContext, actionBindingContext, new TestController()); + .BindActionArgumentsAsync(controllerContext, new TestController()); // Assert Assert.Empty(result); @@ -120,22 +111,15 @@ namespace Microsoft.AspNet.Mvc.Controllers }) .Returns(ModelBindingResult.SuccessAsync(string.Empty, value)); - var actionContext = new ActionContext( - new DefaultHttpContext(), - new RouteData(), - actionDescriptor); - - var actionBindingContext = new ActionBindingContext() - { - ModelBinder = binder.Object, - ValueProvider = new SimpleValueProvider(), - }; + var controllerContext = GetControllerContext(actionDescriptor); + controllerContext.ModelBinders.Add(binder.Object); + controllerContext.ValueProviders.Add(new SimpleValueProvider()); var argumentBinder = GetArgumentBinder(); // Act var result = await argumentBinder - .BindActionArgumentsAsync(actionContext, actionBindingContext, new TestController()); + .BindActionArgumentsAsync(controllerContext, new TestController()); // Assert Assert.Equal(1, result.Count); @@ -154,8 +138,7 @@ namespace Microsoft.AspNet.Mvc.Controllers ParameterType = typeof(object), }); - var actionContext = GetActionContext(actionDescriptor); - var actionBindingContext = GetActionBindingContext(); + var controllerContext = GetControllerContext(actionDescriptor, "Hello"); var mockValidator = new Mock(MockBehavior.Strict); mockValidator @@ -169,8 +152,7 @@ namespace Microsoft.AspNet.Mvc.Controllers var argumentBinder = GetArgumentBinder(mockValidator.Object); // Act - var result = await argumentBinder - .BindActionArgumentsAsync(actionContext, actionBindingContext, new TestController()); + var result = await argumentBinder.BindActionArgumentsAsync(controllerContext, new TestController()); // Assert mockValidator @@ -197,21 +179,14 @@ namespace Microsoft.AspNet.Mvc.Controllers BindingInfo = new BindingInfo(), }); - var actionContext = new ActionContext( - new DefaultHttpContext(), - new RouteData(), - actionDescriptor); - var binder = new Mock(); binder .Setup(b => b.BindModelAsync(It.IsAny())) .Returns(ModelBindingResult.NoResultAsync); - var actionBindingContext = new ActionBindingContext() - { - ModelBinder = binder.Object, - ValueProvider = new SimpleValueProvider(), - }; + var controllerContext = GetControllerContext(actionDescriptor); + controllerContext.ModelBinders.Add(binder.Object); + controllerContext.ValueProviders.Add(new SimpleValueProvider()); var mockValidator = new Mock(MockBehavior.Strict); mockValidator @@ -225,8 +200,7 @@ namespace Microsoft.AspNet.Mvc.Controllers var argumentBinder = GetArgumentBinder(mockValidator.Object); // Act - var result = await argumentBinder - .BindActionArgumentsAsync(actionContext, actionBindingContext, new TestController()); + var result = await argumentBinder.BindActionArgumentsAsync(controllerContext, new TestController()); // Assert mockValidator @@ -251,8 +225,7 @@ namespace Microsoft.AspNet.Mvc.Controllers ParameterType = typeof(string), }); - var actionContext = GetActionContext(actionDescriptor); - var actionBindingContext = GetActionBindingContext(); + var controllerContext = GetControllerContext(actionDescriptor, "Hello"); var mockValidator = new Mock(MockBehavior.Strict); mockValidator @@ -266,8 +239,7 @@ namespace Microsoft.AspNet.Mvc.Controllers var argumentBinder = GetArgumentBinder(mockValidator.Object); // Act - var result = await argumentBinder - .BindActionArgumentsAsync(actionContext, actionBindingContext, new TestController()); + var result = await argumentBinder.BindActionArgumentsAsync(controllerContext, new TestController()); // Assert mockValidator @@ -293,21 +265,14 @@ namespace Microsoft.AspNet.Mvc.Controllers ParameterType = typeof(string), }); - var actionContext = new ActionContext( - new DefaultHttpContext(), - new RouteData(), - actionDescriptor); - var binder = new Mock(); binder .Setup(b => b.BindModelAsync(It.IsAny())) .Returns(ModelBindingResult.NoResultAsync); - var actionBindingContext = new ActionBindingContext() - { - ModelBinder = binder.Object, - ValueProvider = new SimpleValueProvider(), - }; + var controllerContext = GetControllerContext(actionDescriptor); + controllerContext.ModelBinders.Add(binder.Object); + controllerContext.ValueProviders.Add(new SimpleValueProvider()); var mockValidator = new Mock(MockBehavior.Strict); mockValidator @@ -321,8 +286,7 @@ namespace Microsoft.AspNet.Mvc.Controllers var argumentBinder = GetArgumentBinder(mockValidator.Object); // Act - var result = await argumentBinder - .BindActionArgumentsAsync(actionContext, actionBindingContext, new TestController()); + var result = await argumentBinder.BindActionArgumentsAsync(controllerContext, new TestController()); // Assert mockValidator @@ -348,13 +312,12 @@ namespace Microsoft.AspNet.Mvc.Controllers ParameterType = typeof(string) }); - var actionContext = GetActionContext(actionDescriptor); - var actionBindingContext = GetActionBindingContext(); + var controllerContext = GetControllerContext(actionDescriptor, "Hello"); var argumentBinder = GetArgumentBinder(); var controller = new TestController(); // Act - var result = await argumentBinder.BindActionArgumentsAsync(actionContext, actionBindingContext, controller); + var result = await argumentBinder.BindActionArgumentsAsync(controllerContext, controller); // Assert Assert.Equal("Hello", controller.StringProperty); @@ -376,13 +339,13 @@ namespace Microsoft.AspNet.Mvc.Controllers }); var expected = new List { "Hello", "World", "!!" }; - var actionContext = GetActionContext(actionDescriptor); - var actionBindingContext = GetActionBindingContext(model: expected); + var controllerContext = GetControllerContext(actionDescriptor, expected); + var argumentBinder = GetArgumentBinder(); var controller = new TestController(); // Act - var result = await argumentBinder.BindActionArgumentsAsync(actionContext, actionBindingContext, controller); + var result = await argumentBinder.BindActionArgumentsAsync(controllerContext, controller); // Assert Assert.Equal(expected, controller.CollectionProperty); @@ -405,18 +368,14 @@ namespace Microsoft.AspNet.Mvc.Controllers ParameterType = typeof(int) }); - var actionContext = GetActionContext(actionDescriptor); - var binder = new Mock(); binder .Setup(b => b.BindModelAsync(It.IsAny())) .Returns(ModelBindingResult.SuccessAsync(string.Empty, model: null)); - var actionBindingContext = new ActionBindingContext() - { - ModelBinder = binder.Object, - ValueProvider = new SimpleValueProvider(), - }; + var controllerContext = GetControllerContext(actionDescriptor); + controllerContext.ModelBinders.Add(binder.Object); + controllerContext.ValueProviders.Add(new SimpleValueProvider()); var argumentBinder = GetArgumentBinder(); var controller = new TestController(); @@ -425,7 +384,7 @@ namespace Microsoft.AspNet.Mvc.Controllers controller.NonNullableProperty = -1; // Act - var result = await argumentBinder.BindActionArgumentsAsync(actionContext, actionBindingContext, controller); + var result = await argumentBinder.BindActionArgumentsAsync(controllerContext, controller); // Assert Assert.Equal(-1, controller.NonNullableProperty); @@ -444,18 +403,14 @@ namespace Microsoft.AspNet.Mvc.Controllers ParameterType = typeof(int?) }); - var actionContext = GetActionContext(actionDescriptor); - var binder = new Mock(); binder .Setup(b => b.BindModelAsync(It.IsAny())) .Returns(ModelBindingResult.SuccessAsync(key: string.Empty, model: null)); - var actionBindingContext = new ActionBindingContext() - { - ModelBinder = binder.Object, - ValueProvider = new SimpleValueProvider(), - }; + var controllerContext = GetControllerContext(actionDescriptor); + controllerContext.ModelBinders.Add(binder.Object); + controllerContext.ValueProviders.Add(new SimpleValueProvider()); var argumentBinder = GetArgumentBinder(); var controller = new TestController(); @@ -464,7 +419,7 @@ namespace Microsoft.AspNet.Mvc.Controllers controller.NullableProperty = -1; // Act - var result = await argumentBinder.BindActionArgumentsAsync(actionContext, actionBindingContext, controller); + var result = await argumentBinder.BindActionArgumentsAsync(controllerContext, controller); // Assert Assert.Null(controller.NullableProperty); @@ -528,13 +483,12 @@ namespace Microsoft.AspNet.Mvc.Controllers ParameterType = propertyType, }); - var actionContext = GetActionContext(actionDescriptor); - var actionBindingContext = GetActionBindingContext(model: inputValue); + var controllerContext = GetControllerContext(actionDescriptor, inputValue); var argumentBinder = GetArgumentBinder(); var controller = new TestController(); // Act - var result = await argumentBinder.BindActionArgumentsAsync(actionContext, actionBindingContext, controller); + var result = await argumentBinder.BindActionArgumentsAsync(controllerContext, controller); // Assert Assert.Equal(expectedValue, propertyAccessor(controller)); @@ -583,16 +537,19 @@ namespace Microsoft.AspNet.Mvc.Controllers }); } - var actionContext = GetActionContext(actionDescriptor); + var controllerContext = GetControllerContext(actionDescriptor); var argumentBinder = GetArgumentBinder(); var controller = new TestController(); + var binder = new Mock(); binder .Setup(b => b.BindModelAsync(It.IsAny())) .Returns(bindingContext => { + // BindingContext.ModelName will be string.Empty here. This is a 'fallback to empty prefix' + // because the value providers have no data. object model; - if (inputPropertyValues.TryGetValue(bindingContext.ModelName, out model)) + if (inputPropertyValues.TryGetValue(bindingContext.FieldName, out model)) { return ModelBindingResult.SuccessAsync(bindingContext.ModelName, model); } @@ -601,14 +558,11 @@ namespace Microsoft.AspNet.Mvc.Controllers return ModelBindingResult.FailedAsync(bindingContext.ModelName); } }); - var actionBindingContext = new ActionBindingContext - { - ModelBinder = binder.Object, - ValueProvider = new SimpleValueProvider(), - }; + controllerContext.ModelBinders.Add(binder.Object); + controllerContext.ValueProviders.Add(new SimpleValueProvider()); // Act - var result = await argumentBinder.BindActionArgumentsAsync(actionContext, actionBindingContext, controller); + var result = await argumentBinder.BindActionArgumentsAsync(controllerContext, controller); // Assert Assert.Equal(new string[] { "goodbye" }, controller.ArrayProperty); // Skipped @@ -619,15 +573,19 @@ namespace Microsoft.AspNet.Mvc.Controllers Assert.Equal("Hello", controller.StringProperty); } - private static ActionContext GetActionContext(ActionDescriptor descriptor = null) + private static ControllerContext GetControllerContext(ControllerActionDescriptor descriptor = null) { - return new ActionContext( - new DefaultHttpContext(), - new RouteData(), - descriptor ?? GetActionDescriptor()); + var context = new ControllerContext() + { + ActionDescriptor = descriptor ?? GetActionDescriptor(), + HttpContext = new DefaultHttpContext(), + RouteData = new RouteData(), + }; + + return context; } - private static ActionDescriptor GetActionDescriptor() + private static ControllerActionDescriptor GetActionDescriptor() { Func method = foo => 1; return new ControllerActionDescriptor @@ -639,13 +597,15 @@ namespace Microsoft.AspNet.Mvc.Controllers }; } - private static ActionBindingContext GetActionBindingContext() + private static ControllerContext GetControllerContext(ControllerActionDescriptor descriptor = null, object model = null) { - return GetActionBindingContext("Hello"); - } + var context = new ControllerContext() + { + ActionDescriptor = descriptor ?? GetActionDescriptor(), + HttpContext = new DefaultHttpContext(), + RouteData = new RouteData(), + }; - private static ActionBindingContext GetActionBindingContext(object model) - { var binder = new Mock(); binder.Setup(b => b.BindModelAsync(It.IsAny())) .Returns(mbc => @@ -653,11 +613,9 @@ namespace Microsoft.AspNet.Mvc.Controllers return ModelBindingResult.SuccessAsync(string.Empty, model); }); - return new ActionBindingContext() - { - ModelBinder = binder.Object, - ValueProvider = new SimpleValueProvider(), - }; + context.ModelBinders.Add(binder.Object); + context.ValueProviders.Add(new SimpleValueProvider()); + return context; } private static DefaultControllerActionArgumentBinder GetArgumentBinder(IObjectModelValidator validator = null) diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Controllers/ControllerActionInvokerTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Controllers/ControllerActionInvokerTest.cs index b8efc5419a..6722ac4266 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Controllers/ControllerActionInvokerTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Controllers/ControllerActionInvokerTest.cs @@ -2040,7 +2040,7 @@ namespace Microsoft.AspNet.Mvc.Controllers var actionArgumentsBinder = new Mock(); actionArgumentsBinder.Setup( - b => b.BindActionArgumentsAsync(actionContext, It.IsAny(), It.IsAny())) + b => b.BindActionArgumentsAsync(It.IsAny(), It.IsAny())) .Returns(Task.FromResult>(new Dictionary())); filterProvider @@ -2053,12 +2053,10 @@ namespace Microsoft.AspNet.Mvc.Controllers new MockControllerFactory(this), actionDescriptor, new IInputFormatter[0], - new IOutputFormatter[0], actionArgumentsBinder.Object, new IModelBinder[0], new IModelValidatorProvider[0], new IValueProviderFactory[0], - new ActionBindingContextAccessor(), new NullLoggerFactory().CreateLogger(), new DiagnosticListener("Microsoft.AspNet"), maxAllowedErrorsInModelState); @@ -2101,7 +2099,7 @@ namespace Microsoft.AspNet.Mvc.Controllers var actionContext = new ActionContext(context.Object, new RouteData(), actionDescriptor); var controllerFactory = new Mock(); - controllerFactory.Setup(c => c.CreateController(It.IsAny())) + controllerFactory.Setup(c => c.CreateController(It.IsAny())) .Returns(new TestController()); var metadataProvider = new EmptyModelMetadataProvider(); @@ -2112,14 +2110,12 @@ namespace Microsoft.AspNet.Mvc.Controllers controllerFactory.Object, actionDescriptor, new IInputFormatter[0], - new IOutputFormatter[0], new DefaultControllerActionArgumentBinder( metadataProvider, new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], metadataProvider)), new IModelBinder[] { binder.Object }, new IModelValidatorProvider[0], new IValueProviderFactory[0], - new ActionBindingContextAccessor(), new NullLoggerFactory().CreateLogger(), new DiagnosticListener("Microsoft.AspNet"), 200); @@ -2204,7 +2200,7 @@ namespace Microsoft.AspNet.Mvc.Controllers public bool ReleaseCalled { get; private set; } - public object CreateController(ActionContext actionContext) + public object CreateController(ControllerContext context) { CreateCalled = true; return _controller; @@ -2234,12 +2230,10 @@ namespace Microsoft.AspNet.Mvc.Controllers MockControllerFactory controllerFactory, ControllerActionDescriptor descriptor, IReadOnlyList inputFormatters, - IReadOnlyList outputFormatters, IControllerActionArgumentBinder controllerActionArgumentBinder, IReadOnlyList modelBinders, IReadOnlyList modelValidatorProviders, IReadOnlyList valueProviderFactories, - IActionBindingContextAccessor actionBindingContext, ILogger logger, DiagnosticSource diagnosticSource, int maxAllowedErrorsInModelState) @@ -2249,12 +2243,10 @@ namespace Microsoft.AspNet.Mvc.Controllers controllerFactory, descriptor, inputFormatters, - outputFormatters, controllerActionArgumentBinder, modelBinders, modelValidatorProviders, valueProviderFactories, - actionBindingContext, logger, diagnosticSource, maxAllowedErrorsInModelState) diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Controllers/DefaultControllerFactoryTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Controllers/DefaultControllerFactoryTest.cs index 0a81658807..1a0ac9c3da 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Controllers/DefaultControllerFactoryTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Controllers/DefaultControllerFactoryTest.cs @@ -4,12 +4,9 @@ using System; using System.Reflection; using Microsoft.AspNet.Http.Internal; -using Microsoft.AspNet.Mvc.Abstractions; using Microsoft.AspNet.Mvc.Infrastructure; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding.Validation; -using Microsoft.AspNet.Routing; -using Microsoft.Extensions.DependencyInjection; using Moq; using Xunit; @@ -17,27 +14,6 @@ namespace Microsoft.AspNet.Mvc.Controllers { public class DefaultControllerFactoryTest { - [Fact] - public void CreateController_ThrowsIfActionDescriptorIsNotControllerActionDescriptor() - { - // Arrange - var expected = - $"The action descriptor must be of type '{typeof(ControllerActionDescriptor).FullName}'." + - Environment.NewLine + "Parameter name: actionContext"; - var actionDescriptor = new ActionDescriptor(); - var controllerFactory = CreateControllerFactory(); - var httpContext = new DefaultHttpContext(); - var actionContext = new ActionContext(httpContext, - new RouteData(), - actionDescriptor); - - // Act and Assert - var ex = Assert.Throws(() => - controllerFactory.CreateController(actionContext)); - Assert.Equal(expected, ex.Message); - Assert.Equal("actionContext", ex.ParamName); - } - [Fact] public void CreateController_UsesControllerActivatorToInstantiateController() { @@ -47,20 +23,25 @@ namespace Microsoft.AspNet.Mvc.Controllers { ControllerTypeInfo = typeof(MyController).GetTypeInfo() }; - var httpContext = new DefaultHttpContext(); - httpContext.RequestServices = GetServices(); - var actionContext = new ActionContext(httpContext, - new RouteData(), - actionDescriptor); + + var context = new ControllerContext() + { + ActionDescriptor = actionDescriptor, + HttpContext = new DefaultHttpContext() + { + RequestServices = GetServices(), + }, + }; + var activator = new Mock(); - activator.Setup(a => a.Create(actionContext, typeof(MyController))) + activator.Setup(a => a.Create(context, typeof(MyController))) .Returns(expected) .Verifiable(); var controllerFactory = CreateControllerFactory(activator.Object); // Act - var result = controllerFactory.CreateController(actionContext); + var result = controllerFactory.CreateController(context); // Assert var controller = Assert.IsType(result); @@ -76,12 +57,15 @@ namespace Microsoft.AspNet.Mvc.Controllers { ControllerTypeInfo = typeof(ControllerWithAttributes).GetTypeInfo() }; - var services = GetServices(); - var httpContext = new DefaultHttpContext + + var context = new ControllerContext() { - RequestServices = services + ActionDescriptor = actionDescriptor, + HttpContext = new DefaultHttpContext() + { + RequestServices = GetServices(), + }, }; - var context = new ActionContext(httpContext, new RouteData(), actionDescriptor); var factory = CreateControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache())); // Act @@ -93,22 +77,22 @@ namespace Microsoft.AspNet.Mvc.Controllers } [Fact] - public void CreateController_SetsBindingContext() + public void CreateController_SetsControllerContext() { // Arrange var actionDescriptor = new ControllerActionDescriptor { ControllerTypeInfo = typeof(ControllerWithAttributes).GetTypeInfo() }; - var bindingContext = new ActionBindingContext(); - var services = GetServices(); - services.GetRequiredService().ActionBindingContext = bindingContext; - var httpContext = new DefaultHttpContext + var context = new ControllerContext() { - RequestServices = services + ActionDescriptor = actionDescriptor, + HttpContext = new DefaultHttpContext() + { + RequestServices = GetServices(), + }, }; - var context = new ActionContext(httpContext, new RouteData(), actionDescriptor); var factory = CreateControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache())); // Act @@ -116,7 +100,7 @@ namespace Microsoft.AspNet.Mvc.Controllers // Assert var controller = Assert.IsType(result); - Assert.Same(bindingContext, controller.BindingContext); + Assert.Same(context, controller.ControllerContext); } [Fact] @@ -127,12 +111,15 @@ namespace Microsoft.AspNet.Mvc.Controllers { ControllerTypeInfo = typeof(ControllerWithoutAttributes).GetTypeInfo() }; - var services = GetServices(); - var httpContext = new DefaultHttpContext + + var context = new ControllerContext() { - RequestServices = services + ActionDescriptor = actionDescriptor, + HttpContext = new DefaultHttpContext() + { + RequestServices = GetServices(), + }, }; - var context = new ActionContext(httpContext, new RouteData(), actionDescriptor); var factory = CreateControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache())); // Act @@ -151,12 +138,15 @@ namespace Microsoft.AspNet.Mvc.Controllers { ControllerTypeInfo = typeof(ControllerWithNonVisibleProperties).GetTypeInfo() }; - var services = GetServices(); - var httpContext = new DefaultHttpContext + + var context = new ControllerContext() { - RequestServices = services + ActionDescriptor = actionDescriptor, + HttpContext = new DefaultHttpContext() + { + RequestServices = GetServices(), + }, }; - var context = new ActionContext(httpContext, new RouteData(), actionDescriptor); var factory = CreateControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache())); // Act @@ -165,7 +155,7 @@ namespace Microsoft.AspNet.Mvc.Controllers // Assert var controller = Assert.IsType(result); Assert.Null(controller.ActionContext); - Assert.Null(controller.BindingContext); + Assert.Null(controller.ControllerContext); } [Fact] @@ -176,12 +166,15 @@ namespace Microsoft.AspNet.Mvc.Controllers { ControllerTypeInfo = typeof(ControllerThatCannotBeActivated).GetTypeInfo() }; - var services = GetServices(); - var httpContext = new DefaultHttpContext + + var context = new ControllerContext() { - RequestServices = services + ActionDescriptor = actionDescriptor, + HttpContext = new DefaultHttpContext() + { + RequestServices = GetServices(), + }, }; - var context = new ActionContext(httpContext, new RouteData(), actionDescriptor); var factory = CreateControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache())); // Act and Assert @@ -204,12 +197,15 @@ namespace Microsoft.AspNet.Mvc.Controllers { ControllerTypeInfo = type.GetTypeInfo() }; - var services = GetServices(); - var httpContext = new DefaultHttpContext + + var context = new ControllerContext() { - RequestServices = services + ActionDescriptor = actionDescriptor, + HttpContext = new DefaultHttpContext() + { + RequestServices = GetServices(), + }, }; - var context = new ActionContext(httpContext, new RouteData(), actionDescriptor); var factory = CreateControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache())); // Act and Assert @@ -256,8 +252,6 @@ namespace Microsoft.AspNet.Mvc.Controllers .Returns(metadataProvider); services.Setup(s => s.GetService(typeof(IObjectModelValidator))) .Returns(new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], metadataProvider)); - services.Setup(s => s.GetService(typeof(IActionBindingContextAccessor))) - .Returns(new ActionBindingContextAccessor()); return services.Object; } @@ -266,7 +260,7 @@ namespace Microsoft.AspNet.Mvc.Controllers controllerActivator = controllerActivator ?? Mock.Of(); var propertyActivators = new IControllerPropertyActivator[] { - new DefaultControllerPropertyActivator(new ActionBindingContextAccessor()), + new DefaultControllerPropertyActivator(), }; return new DefaultControllerFactory(controllerActivator, propertyActivators); @@ -276,14 +270,14 @@ namespace Microsoft.AspNet.Mvc.Controllers { public ActionContext ActionContext { get; set; } - public ActionBindingContext BindingContext { get; set; } + public ControllerContext ControllerContext { get; set; } } public class ControllerWithNonVisibleProperties { internal ActionContext ActionContext { get; set; } - public ActionBindingContext BindingContext { get; private set; } + public ControllerContext ControllerContext { get; private set; } } private class ControllerWithAttributes @@ -291,8 +285,8 @@ namespace Microsoft.AspNet.Mvc.Controllers [ActionContext] public ActionContext ActionContext { get; set; } - [ActionBindingContext] - public ActionBindingContext BindingContext { get; set; } + [ControllerContext] + public ControllerContext ControllerContext { get; set; } } private class MyController : IDisposable diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/CreatedAtActionResultTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/CreatedAtActionResultTests.cs index 298734f9db..2660094638 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/CreatedAtActionResultTests.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/CreatedAtActionResultTests.cs @@ -97,7 +97,6 @@ namespace Microsoft.AspNet.Mvc var services = new ServiceCollection(); services.AddSingleton(new ObjectResultExecutor( options, - new ActionBindingContextAccessor(), new TestHttpResponseStreamWriterFactory(), NullLoggerFactory.Instance)); diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/CreatedAtRouteResultTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/CreatedAtRouteResultTests.cs index c61e561aac..43ba24be0a 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/CreatedAtRouteResultTests.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/CreatedAtRouteResultTests.cs @@ -111,7 +111,6 @@ namespace Microsoft.AspNet.Mvc var services = new ServiceCollection(); services.AddSingleton(new ObjectResultExecutor( options, - new ActionBindingContextAccessor(), new TestHttpResponseStreamWriterFactory(), NullLoggerFactory.Instance)); diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/CreatedResultTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/CreatedResultTests.cs index d063613234..08e95aab79 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/CreatedResultTests.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/CreatedResultTests.cs @@ -98,7 +98,6 @@ namespace Microsoft.AspNet.Mvc var services = new ServiceCollection(); services.AddSingleton(new ObjectResultExecutor( options, - new ActionBindingContextAccessor(), new TestHttpResponseStreamWriterFactory(), NullLoggerFactory.Instance)); diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/HttpNotFoundObjectResultTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/HttpNotFoundObjectResultTest.cs index afefe2051c..dc41479212 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/HttpNotFoundObjectResultTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/HttpNotFoundObjectResultTest.cs @@ -74,7 +74,6 @@ namespace Microsoft.AspNet.Mvc var services = new ServiceCollection(); services.AddSingleton(new ObjectResultExecutor( options, - new ActionBindingContextAccessor(), new TestHttpResponseStreamWriterFactory(), NullLoggerFactory.Instance)); diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/HttpOkObjectResultTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/HttpOkObjectResultTest.cs index e59e4baf3e..593027fe4e 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/HttpOkObjectResultTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/HttpOkObjectResultTest.cs @@ -78,7 +78,6 @@ namespace Microsoft.AspNet.Mvc var services = new ServiceCollection(); services.AddSingleton(new ObjectResultExecutor( options, - new ActionBindingContextAccessor(), new TestHttpResponseStreamWriterFactory(), NullLoggerFactory.Instance)); diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/DefaultActionSelectorTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/DefaultActionSelectorTests.cs index 13bbc79079..81b7b4af82 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/DefaultActionSelectorTests.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/DefaultActionSelectorTests.cs @@ -573,11 +573,9 @@ namespace Microsoft.AspNet.Mvc.Infrastructure var actionDescriptorProvider = GetActionDescriptorProvider(); // Act - var result = actionDescriptorProvider.GetDescriptors() - .Select(x => x as ControllerActionDescriptor) - .FirstOrDefault( - x => x.ControllerName == "NonAction" && - x.Name == actionName); + var result = actionDescriptorProvider + .GetDescriptors() + .FirstOrDefault(x => x.ControllerName == "NonAction" && x.Name == actionName); // Assert Assert.Null(result); diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/ObjectResultExecutorTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/ObjectResultExecutorTest.cs index 3589b0a281..ea088a1412 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/ObjectResultExecutorTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/ObjectResultExecutorTest.cs @@ -261,7 +261,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure var result = new ObjectResult("input"); // This formatter won't write anything - result.Formatters = new List + result.Formatters = new FormatterCollection { new CannotWriteFormatter(), }; @@ -273,36 +273,6 @@ namespace Microsoft.AspNet.Mvc.Infrastructure Assert.Equal(StatusCodes.Status406NotAcceptable, actionContext.HttpContext.Response.StatusCode); } - [Fact] - public async Task ExecuteAsync_FallsBackOnFormattersInBindingContext() - { - // Arrange - var bindingContext = new ActionBindingContext() - { - OutputFormatters = new List() - { - new TestJsonOutputFormatter(), - } - }; - - var executor = CreateExecutor(bindingContext: bindingContext); - - var actionContext = new ActionContext() - { - HttpContext = GetHttpContext(), - }; - - var result = new ObjectResult("someValue"); - - // Act - await executor.ExecuteAsync(actionContext, result); - - // Assert - Assert.Equal( - "application/json; charset=utf-8", - actionContext.HttpContext.Response.Headers[HeaderNames.ContentType]); - } - [Fact] public async Task ExecuteAsync_FallsBackOnFormattersInOptions() { @@ -450,19 +420,10 @@ namespace Microsoft.AspNet.Mvc.Infrastructure return httpContext; } - private static TestObjectResultExecutor CreateExecutor( - IOptions options = null, - ActionBindingContext bindingContext = null) + private static TestObjectResultExecutor CreateExecutor(IOptions options = null) { - var bindingContextAccessor = new ActionBindingContextAccessor(); - if (bindingContext != null) - { - bindingContextAccessor.ActionBindingContext = bindingContext; - } - return new TestObjectResultExecutor( options ?? new TestOptionsManager(), - bindingContextAccessor, new TestHttpResponseStreamWriterFactory(), NullLoggerFactory.Instance); } @@ -516,10 +477,9 @@ namespace Microsoft.AspNet.Mvc.Infrastructure { public TestObjectResultExecutor( IOptions options, - IActionBindingContextAccessor bindingContextAccessor, IHttpResponseStreamWriterFactory writerFactory, ILoggerFactory loggerFactory) - : base(options, bindingContextAccessor, writerFactory, loggerFactory) + : base(options, writerFactory, loggerFactory) { } diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/FormValueProviderFactoryTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/FormValueProviderFactoryTest.cs index 355957f7c4..e4655592be 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/FormValueProviderFactoryTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/FormValueProviderFactoryTest.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using System.Globalization; using System.Threading.Tasks; using Microsoft.AspNet.Http.Internal; +using Microsoft.AspNet.Mvc.Abstractions; +using Microsoft.AspNet.Routing; using Microsoft.Extensions.Primitives; using Xunit; @@ -46,7 +48,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test Assert.Equal(CultureInfo.CurrentCulture, valueProvider.Culture); } - private static ValueProviderFactoryContext CreateContext(string contentType) + private static ActionContext CreateContext(string contentType) { var context = new DefaultHttpContext(); context.Request.ContentType = contentType; @@ -56,9 +58,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test context.Request.Form = new FormCollection(new Dictionary()); } - return new ValueProviderFactoryContext( - context, - new Dictionary(StringComparer.OrdinalIgnoreCase)); + return new ActionContext(context, new RouteData(), new ActionDescriptor()); } } } diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/JQueryFormValueProviderFactoryTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/JQueryFormValueProviderFactoryTest.cs index 838eca60e8..ad8ecb2960 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/JQueryFormValueProviderFactoryTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/JQueryFormValueProviderFactoryTest.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using System.Globalization; using System.Threading.Tasks; using Microsoft.AspNet.Http.Internal; +using Microsoft.AspNet.Mvc.Abstractions; +using Microsoft.AspNet.Routing; using Microsoft.Extensions.Primitives; using Xunit; @@ -114,9 +116,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test Assert.Equal("found", (string)result); } - private static ValueProviderFactoryContext CreateContext( - string contentType, - Dictionary formValues) + private static ActionContext CreateContext(string contentType, Dictionary formValues) { var context = new DefaultHttpContext(); context.Request.ContentType = contentType; @@ -126,9 +126,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test context.Request.Form = new FormCollection(formValues ?? new Dictionary()); } - return new ValueProviderFactoryContext( - context, - new Dictionary(StringComparer.OrdinalIgnoreCase)); + return new ActionContext(context, new RouteData(), new ActionDescriptor()); } } } diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/QueryStringValueProviderFactoryTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/QueryStringValueProviderFactoryTest.cs index 1aeb3871bf..a13aa7bb5c 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/QueryStringValueProviderFactoryTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/QueryStringValueProviderFactoryTest.cs @@ -2,11 +2,12 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. #if DNX451 -using System; using System.Collections.Generic; using System.Globalization; using System.Threading.Tasks; using Microsoft.AspNet.Http; +using Microsoft.AspNet.Mvc.Abstractions; +using Microsoft.AspNet.Routing; using Moq; using Xunit; #endif @@ -27,12 +28,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test var context = new Mock(); context.SetupGet(c => c.Items).Returns(new Dictionary()); context.SetupGet(c => c.Request).Returns(request.Object); - var factoryContext = new ValueProviderFactoryContext( - context.Object, - new Dictionary(StringComparer.OrdinalIgnoreCase)); + var actionContext = new ActionContext(context.Object, new RouteData(), new ActionDescriptor()); // Act - var result = await _factory.GetValueProviderAsync(factoryContext); + var result = await _factory.GetValueProviderAsync(actionContext); // Assert var valueProvider = Assert.IsType(result); diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ObjectResultTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ObjectResultTests.cs index f1c5edb3ba..71f0dbcf99 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ObjectResultTests.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ObjectResultTests.cs @@ -41,7 +41,7 @@ namespace Microsoft.AspNet.Mvc var result = new ObjectResult("Hello") { StatusCode = 404, - Formatters = new List() + Formatters = new FormatterCollection() { new NoOpOutputFormatter(), }, @@ -67,7 +67,6 @@ namespace Microsoft.AspNet.Mvc var services = new ServiceCollection(); services.AddSingleton(new ObjectResultExecutor( new TestOptionsManager(), - new ActionBindingContextAccessor(), new TestHttpResponseStreamWriterFactory(), NullLoggerFactory.Instance)); services.AddSingleton(NullLoggerFactory.Instance); diff --git a/test/Microsoft.AspNet.Mvc.IntegrationTests/ModelBindingTestHelper.cs b/test/Microsoft.AspNet.Mvc.IntegrationTests/ModelBindingTestHelper.cs index 4cc76b80d8..a8d3fec3f7 100644 --- a/test/Microsoft.AspNet.Mvc.IntegrationTests/ModelBindingTestHelper.cs +++ b/test/Microsoft.AspNet.Mvc.IntegrationTests/ModelBindingTestHelper.cs @@ -2,51 +2,40 @@ // 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.AspNet.Http; using Microsoft.AspNet.Http.Internal; using Microsoft.AspNet.Mvc.Controllers; -using Microsoft.AspNet.Mvc.Infrastructure; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding.Validation; using Microsoft.AspNet.Routing; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.OptionsModel; namespace Microsoft.AspNet.Mvc.IntegrationTests { public static class ModelBindingTestHelper { - public static HttpContext GetHttpContext( - Action updateRequest = null, - Action updateOptions = null) - { - var httpContext = new DefaultHttpContext(); - - if (updateRequest != null) - { - updateRequest(httpContext.Request); - } - - InitializeServices(httpContext, updateOptions); - return httpContext; - } - public static OperationBindingContext GetOperationBindingContext( Action updateRequest = null, Action updateOptions = null) { var httpContext = GetHttpContext(updateRequest, updateOptions); - var services = httpContext.RequestServices; - var actionBindingContext = services.GetRequiredService().ActionBindingContext; + + var actionContext = new ActionContext(httpContext, new RouteData(), new ControllerActionDescriptor()); + var controllerContext = GetControllerContext( + services.GetRequiredService>().Value, + actionContext); return new OperationBindingContext() { HttpContext = httpContext, - InputFormatters = actionBindingContext.InputFormatters, + InputFormatters = controllerContext.InputFormatters, MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(), - ValidatorProvider = actionBindingContext.ValidatorProvider, - ValueProvider = actionBindingContext.ValueProvider, - ModelBinder = actionBindingContext.ModelBinder + ValidatorProvider = new CompositeModelValidatorProvider(controllerContext.ValidatorProviders), + ValueProvider = new CompositeValueProvider(controllerContext.ValueProviders), + ModelBinder = new CompositeModelBinder(controllerContext.ModelBinders), }; } @@ -68,47 +57,47 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests metadataProvider); } - private static void InitializeServices(HttpContext httpContext, Action updateOptions = null) + private static HttpContext GetHttpContext( + Action updateRequest = null, + Action updateOptions = null) { + var httpContext = new DefaultHttpContext(); + + if (updateRequest != null) + { + updateRequest(httpContext.Request); + } + var serviceCollection = new ServiceCollection(); serviceCollection.AddMvc(); - httpContext.RequestServices = serviceCollection.BuildServiceProvider(); - - var actionContext = new ActionContext(httpContext, new RouteData(), new ControllerActionDescriptor()); - - var actionContextAccessor = - httpContext.RequestServices.GetRequiredService(); - actionContextAccessor.ActionContext = actionContext; - - var options = new TestMvcOptions().Value; if (updateOptions != null) { - updateOptions(options); + serviceCollection.Configure(updateOptions); } - var actionBindingContextAccessor = - httpContext.RequestServices.GetRequiredService(); - actionBindingContextAccessor.ActionBindingContext = GetActionBindingContext(options, actionContext); + httpContext.RequestServices = serviceCollection.BuildServiceProvider(); + return httpContext; } - private static ActionBindingContext GetActionBindingContext(MvcOptions options, ActionContext actionContext) + private static ControllerContext GetControllerContext(MvcOptions options, ActionContext context) { - var valueProviderFactoryContext = new ValueProviderFactoryContext( - actionContext.HttpContext, - actionContext.RouteData.Values); + var valueProviders = new List(); + foreach (var factory in options.ValueProviderFactories) + { + var valueProvider = factory.GetValueProviderAsync(context).Result; + if (valueProvider != null) + { + valueProviders.Add(valueProvider); + } + } - var valueProvider = CompositeValueProvider.CreateAsync( - options.ValueProviderFactories, - valueProviderFactoryContext).Result; - - return new ActionBindingContext() + return new ControllerContext(context) { InputFormatters = options.InputFormatters, - OutputFormatters = options.OutputFormatters, // Not required for model binding. - ValidatorProvider = new TestModelValidatorProvider(options.ModelValidatorProviders), - ModelBinder = new CompositeModelBinder(options.ModelBinders), - ValueProvider = valueProvider + ValidatorProviders = options.ModelValidatorProviders, + ModelBinders = options.ModelBinders, + ValueProviders = valueProviders }; } } diff --git a/test/Microsoft.AspNet.Mvc.IntegrationTests/MutableObjectModelBinderIntegrationTest.cs b/test/Microsoft.AspNet.Mvc.IntegrationTests/MutableObjectModelBinderIntegrationTest.cs index 0f7143d1ca..52aeffc176 100644 --- a/test/Microsoft.AspNet.Mvc.IntegrationTests/MutableObjectModelBinderIntegrationTest.cs +++ b/test/Microsoft.AspNet.Mvc.IntegrationTests/MutableObjectModelBinderIntegrationTest.cs @@ -1351,6 +1351,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests var model = Assert.IsType(modelBindingResult.Model); Assert.NotNull(model.Customer); + Assert.NotNull(model.Customer.Address); Assert.Equal(AddressStreetContent, model.Customer.Address.Street); diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ControllerTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ControllerTest.cs index 2248216997..63f782a0bf 100644 --- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ControllerTest.cs +++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ControllerTest.cs @@ -11,7 +11,6 @@ using System.Text; using System.Threading.Tasks; using Microsoft.AspNet.Http; using Microsoft.AspNet.Http.Internal; -using Microsoft.AspNet.Mvc.Abstractions; using Microsoft.AspNet.Mvc.Filters; using Microsoft.AspNet.Mvc.Formatters; using Microsoft.AspNet.Mvc.ModelBinding; @@ -479,10 +478,9 @@ namespace Microsoft.AspNet.Mvc.Test mockHttpContext.Setup(x => x.Response.RegisterForDispose(It.IsAny())); var uri = new Uri("/test/url", UriKind.Relative); - var controller = new TestableController() - { - ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()) - }; + var controller = new TestableController(); + controller.ControllerContext.HttpContext = mockHttpContext.Object; + var input = new DisposableObject(); // Act @@ -565,10 +563,9 @@ namespace Microsoft.AspNet.Mvc.Test var mockHttpContext = new Mock(); mockHttpContext.Setup(x => x.Response.RegisterForDispose(It.IsAny())); - var controller = new TestableController() - { - ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()) - }; + var controller = new TestableController(); + controller.ControllerContext.HttpContext = mockHttpContext.Object; + var input = new DisposableObject(); // Act @@ -648,10 +645,9 @@ namespace Microsoft.AspNet.Mvc.Test var mockHttpContext = new Mock(); mockHttpContext.Setup(x => x.Response.RegisterForDispose(It.IsAny())); - var controller = new TestableController() - { - ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()) - }; + var controller = new TestableController(); + controller.ControllerContext.HttpContext = mockHttpContext.Object; + var input = new DisposableObject(); // Act @@ -741,10 +737,10 @@ namespace Microsoft.AspNet.Mvc.Test // Arrange var mockHttpContext = new Mock(); mockHttpContext.Setup(x => x.Response.RegisterForDispose(It.IsAny())); - var controller = new TestableController() - { - ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()) - }; + + var controller = new TestableController(); + controller.ControllerContext.HttpContext = mockHttpContext.Object; + var fileStream = Stream.Null; // Act @@ -764,10 +760,9 @@ namespace Microsoft.AspNet.Mvc.Test var mockHttpContext = new Mock(); mockHttpContext.Setup(x => x.Response.RegisterForDispose(It.IsAny())); - var controller = new TestableController() - { - ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()) - }; + var controller = new TestableController(); + controller.ControllerContext.HttpContext = mockHttpContext.Object; + var fileStream = Stream.Null; // Act @@ -833,10 +828,9 @@ namespace Microsoft.AspNet.Mvc.Test var mockHttpContext = new Mock(); mockHttpContext.Setup(x => x.Response.RegisterForDispose(It.IsAny())); - var controller = new TestableController() - { - ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()) - }; + var controller = new TestableController(); + controller.ControllerContext.HttpContext = mockHttpContext.Object; + var input = new DisposableObject(); // Act @@ -872,10 +866,9 @@ namespace Microsoft.AspNet.Mvc.Test var mockHttpContext = new Mock(); mockHttpContext.Setup(x => x.Response.RegisterForDispose(It.IsAny())); - var controller = new TestableController() - { - ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()) - }; + var controller = new TestableController(); + controller.ControllerContext.HttpContext = mockHttpContext.Object; + var input = new DisposableObject(); // Act @@ -927,10 +920,9 @@ namespace Microsoft.AspNet.Mvc.Test var mockHttpContext = new Mock(); mockHttpContext.Setup(x => x.Response.RegisterForDispose(It.IsAny())); - var controller = new TestableController() - { - ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()) - }; + var controller = new TestableController(); + controller.ControllerContext.HttpContext = mockHttpContext.Object; + var input = new DisposableObject(); // Act @@ -1153,10 +1145,9 @@ namespace Microsoft.AspNet.Mvc.Test var mockHttpContext = new Mock(); mockHttpContext.Setup(x => x.Response.RegisterForDispose(It.IsAny())); - var controller = new TestableController() - { - ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()) - }; + var controller = new TestableController(); + controller.ControllerContext.HttpContext = mockHttpContext.Object; + var input = new DisposableObject(); // Act @@ -1177,10 +1168,9 @@ namespace Microsoft.AspNet.Mvc.Test var mockHttpContext = new Mock(); mockHttpContext.Setup(x => x.Response.RegisterForDispose(It.IsAny())); - var controller = new TestableController() - { - ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()) - }; + var controller = new TestableController(); + controller.ControllerContext.HttpContext = mockHttpContext.Object; + var input = new DisposableObject(); var serializerSettings = new JsonSerializerSettings(); @@ -1255,7 +1245,7 @@ namespace Microsoft.AspNet.Mvc.Test .Callback((ModelBindingContext context) => { Assert.Empty(context.ModelName); - Assert.Same(valueProvider, context.ValueProvider); + Assert.Same(valueProvider, Assert.IsType(context.ValueProvider)[0]); // Include and exclude should be null, resulting in property // being included. @@ -1287,8 +1277,7 @@ namespace Microsoft.AspNet.Mvc.Test binder.Setup(b => b.BindModelAsync(It.IsAny())) .Callback((ModelBindingContext context) => { - Assert.Equal(modelName, context.ModelName); - Assert.Same(valueProvider, context.ValueProvider); + Assert.Same(valueProvider, Assert.IsType(context.ValueProvider)[0]); // Include and exclude should be null, resulting in property // being included. @@ -1319,7 +1308,6 @@ namespace Microsoft.AspNet.Mvc.Test binder.Setup(b => b.BindModelAsync(It.IsAny())) .Callback((ModelBindingContext context) => { - Assert.Equal(modelName, context.ModelName); Assert.Same(valueProvider, context.ValueProvider); // Include and exclude should be null, resulting in property @@ -1330,7 +1318,7 @@ namespace Microsoft.AspNet.Mvc.Test .Returns(ModelBindingResult.NoResultAsync) .Verifiable(); - var controller = GetController(binder.Object, provider: null); + var controller = GetController(binder.Object, valueProvider: null); var model = new MyModel(); // Act @@ -1355,8 +1343,7 @@ namespace Microsoft.AspNet.Mvc.Test binder.Setup(b => b.BindModelAsync(It.IsAny())) .Callback((ModelBindingContext context) => { - Assert.Equal(modelName, context.ModelName); - Assert.Same(valueProvider, context.ValueProvider); + Assert.Same(valueProvider, Assert.IsType(context.ValueProvider)[0]); Assert.True(context.PropertyFilter(context, "include1")); Assert.True(context.PropertyFilter(context, "include2")); @@ -1392,7 +1379,6 @@ namespace Microsoft.AspNet.Mvc.Test binder.Setup(b => b.BindModelAsync(It.IsAny())) .Callback((ModelBindingContext context) => { - Assert.Equal(modelName, context.ModelName); Assert.Same(valueProvider, context.ValueProvider); Assert.True(context.PropertyFilter(context, "include1")); @@ -1404,7 +1390,7 @@ namespace Microsoft.AspNet.Mvc.Test .Returns(ModelBindingResult.NoResultAsync) .Verifiable(); - var controller = GetController(binder.Object, provider: null); + var controller = GetController(binder.Object, valueProvider: null); var model = new MyModel(); @@ -1421,13 +1407,18 @@ namespace Microsoft.AspNet.Mvc.Test public async Task TryUpdateModel_IncludeExpressionOverload_UsesPassedArguments(string prefix) { // Arrange + var valueProvider = new Mock(); + valueProvider + .Setup(v => v.ContainsPrefix(prefix)) + .Returns(true); + var binder = new Mock(); - var valueProvider = Mock.Of(); binder.Setup(b => b.BindModelAsync(It.IsAny())) .Callback((ModelBindingContext context) => { - Assert.Equal(prefix, context.ModelName); - Assert.Same(valueProvider, context.ValueProvider); + Assert.Same( + valueProvider.Object, + Assert.IsType(context.ValueProvider)[0]); Assert.True(context.PropertyFilter(context, "Property1")); Assert.True(context.PropertyFilter(context, "Property2")); @@ -1439,7 +1430,7 @@ namespace Microsoft.AspNet.Mvc.Test .Verifiable(); - var controller = GetController(binder.Object, valueProvider); + var controller = GetController(binder.Object, valueProvider.Object); var model = new MyModel(); // Act @@ -1456,12 +1447,15 @@ namespace Microsoft.AspNet.Mvc.Test TryUpdateModel_IncludeExpressionWithValueProviderOverload_UsesPassedArguments(string prefix) { // Arrange - var binder = new Mock(); var valueProvider = new Mock(); + valueProvider + .Setup(v => v.ContainsPrefix(prefix)) + .Returns(true); + + var binder = new Mock(); binder.Setup(b => b.BindModelAsync(It.IsAny())) .Callback((ModelBindingContext context) => { - Assert.Equal(prefix, context.ModelName); Assert.Same(valueProvider.Object, context.ValueProvider); Assert.True(context.PropertyFilter(context, "Property1")); @@ -1473,7 +1467,7 @@ namespace Microsoft.AspNet.Mvc.Test .Returns(ModelBindingResult.NoResultAsync) .Verifiable(); - var controller = GetController(binder.Object, provider: null); + var controller = GetController(binder.Object, valueProvider: null); var model = new MyModel(); // Act @@ -1493,12 +1487,12 @@ namespace Microsoft.AspNet.Mvc.Test (context, propertyName) => string.Equals(propertyName, "include1", StringComparison.OrdinalIgnoreCase) || string.Equals(propertyName, "include2", StringComparison.OrdinalIgnoreCase); - var binder = new Mock(); var valueProvider = Mock.Of(); + + var binder = new Mock(); binder.Setup(b => b.BindModelAsync(It.IsAny())) .Callback((ModelBindingContext context) => { - Assert.Equal(modelName, context.ModelName); Assert.Same(valueProvider, context.ValueProvider); Assert.True(context.PropertyFilter(context, "include1")); @@ -1510,7 +1504,7 @@ namespace Microsoft.AspNet.Mvc.Test .Returns(ModelBindingResult.NoResultAsync) .Verifiable(); - var controller = GetController(binder.Object, provider: null); + var controller = GetController(binder.Object, valueProvider: null); var model = new MyModel(); @@ -1533,8 +1527,7 @@ namespace Microsoft.AspNet.Mvc.Test binder.Setup(b => b.BindModelAsync(It.IsAny())) .Callback((ModelBindingContext context) => { - Assert.Equal(modelName, context.ModelName); - Assert.Same(valueProvider, context.ValueProvider); + Assert.Same(valueProvider, Assert.IsType(context.ValueProvider)[0]); // Include and exclude should be null, resulting in property // being included. @@ -1566,8 +1559,7 @@ namespace Microsoft.AspNet.Mvc.Test binder.Setup(b => b.BindModelAsync(It.IsAny())) .Callback((ModelBindingContext context) => { - Assert.Equal(modelName, context.ModelName); - Assert.Same(valueProvider, context.ValueProvider); + Assert.Same(valueProvider, Assert.IsType(context.ValueProvider)[0]); // Include and exclude should be null, resulting in property // being included. @@ -1600,9 +1592,7 @@ namespace Microsoft.AspNet.Mvc.Test httpContext.Setup(c => c.RequestServices) .Returns(serviceProvider); - controller.ActionContext = new ActionContext(httpContext.Object, - Mock.Of(), - new ActionDescriptor()); + controller.ControllerContext.HttpContext = httpContext.Object; // Act var innerServiceProvider = controller.Resolver; @@ -1622,9 +1612,7 @@ namespace Microsoft.AspNet.Mvc.Test httpContext.Setup(c => c.Request) .Returns(request); - controller.ActionContext = new ActionContext(httpContext.Object, - Mock.Of(), - new ActionDescriptor()); + controller.ControllerContext.HttpContext = httpContext.Object; // Act var innerRequest = controller.Request; @@ -1644,9 +1632,7 @@ namespace Microsoft.AspNet.Mvc.Test httpContext.Setup(c => c.Response) .Returns(response); - controller.ActionContext = new ActionContext(httpContext.Object, - Mock.Of(), - new ActionDescriptor()); + controller.ControllerContext.HttpContext = httpContext.Object; // Act var innerResponse = controller.Response; @@ -1662,10 +1648,7 @@ namespace Microsoft.AspNet.Mvc.Test var controller = new TestableController(); var routeData = Mock.Of(); - - controller.ActionContext = new ActionContext(Mock.Of(), - routeData, - new ActionDescriptor()); + controller.ControllerContext.RouteData = routeData; // Act var innerRouteData = controller.RouteData; @@ -1692,8 +1675,12 @@ namespace Microsoft.AspNet.Mvc.Test { // Arrange var binder = new Mock(); - var controller = GetController(binder.Object, provider: null); - controller.BindingContext.ValidatorProvider = Mock.Of(); + var controller = GetController(binder.Object, valueProvider: null); + controller.ControllerContext.ValidatorProviders = new List() + { + Mock.Of(), + }; + var model = new TryValidateModelModel(); // Act @@ -1724,8 +1711,11 @@ namespace Microsoft.AspNet.Mvc.Test .Callback(c => c.Validators.Add(validator1.Object)); var binder = new Mock(); - var controller = GetController(binder.Object, provider: null); - controller.BindingContext.ValidatorProvider = provider.Object; + var controller = GetController(binder.Object, valueProvider: null); + controller.ControllerContext.ValidatorProviders = new List() + { + provider.Object, + }; // Act var result = controller.TryValidateModel(model, "Prefix"); @@ -1757,8 +1747,11 @@ namespace Microsoft.AspNet.Mvc.Test .Callback(c => c.Validators.Add(validator1.Object)); var binder = new Mock(); - var controller = GetController(binder.Object, provider: null); - controller.BindingContext.ValidatorProvider = provider.Object; + var controller = GetController(binder.Object, valueProvider: null); + controller.ControllerContext.ValidatorProviders = new List() + { + provider.Object, + }; // Act var result = controller.TryValidateModel(model); @@ -1777,7 +1770,7 @@ namespace Microsoft.AspNet.Mvc.Test // Do not add a Mock validator provider to this test. Test is intended to demonstrate ease of unit testing // and exercise DataAnnotationsModelValidatorProvider, avoiding #3586 regressions. var model = new TryValidateModelModel(); - var controller = GetController(binder: null, provider: null); + var controller = GetController(binder: null, valueProvider: null); // Act var result = controller.TryValidateModel(model); @@ -1786,19 +1779,6 @@ namespace Microsoft.AspNet.Mvc.Test Assert.True(controller.ModelState.IsValid); } - [Fact] - public void TryValidateModelEmptyBindingContextThrowsException() - { - // Arrange - var controller = new TestableController(); - var model = new TryValidateModelModel(); - - // Act & Assert - var exception = Assert.Throws(() => controller.TryValidateModel(model)); - Assert.Equal("The 'BindingContext' property of 'Microsoft.AspNet.Mvc.Controller' must not be null.", exception.Message); - } - - [Fact] public void TempData_CanSetAndGetValues() { // Arrange @@ -1813,34 +1793,34 @@ namespace Microsoft.AspNet.Mvc.Test Assert.Equal(input, result); } - private static Controller GetController(IModelBinder binder, IValueProvider provider) + private static Controller GetController(IModelBinder binder, IValueProvider valueProvider) { var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var httpContext = new DefaultHttpContext(); - var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var viewData = new ViewDataDictionary(metadataProvider, new ModelStateDictionary()); var tempData = new TempDataDictionary(Mock.Of(), Mock.Of()); - var bindingContext = new ActionBindingContext() + var controllerContext = new ControllerContext() { - ModelBinder = binder, - ValueProvider = provider, - InputFormatters = new List(), - ValidatorProvider = new DataAnnotationsModelValidatorProvider( - options: null, - stringLocalizerFactory: null) + HttpContext = httpContext, + ModelBinders = new[] { binder, }, + ValueProviders = new[] { valueProvider, }, + ValidatorProviders = new [] + { + new DataAnnotationsModelValidatorProvider(options: null, stringLocalizerFactory: null), + }, }; - return new TestableController() + var controller = new TestableController() { - ActionContext = actionContext, - BindingContext = bindingContext, + ControllerContext = controllerContext, MetadataProvider = metadataProvider, - ViewData = viewData, + ObjectValidator = new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], metadataProvider), TempData = tempData, - ObjectValidator = new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], metadataProvider) + ViewData = viewData, }; + return controller; } private class MyModel diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ControllerUnitTestabilityTests.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ControllerUnitTestabilityTests.cs index a45e89a737..a08585a5a2 100644 --- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ControllerUnitTestabilityTests.cs +++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ControllerUnitTestabilityTests.cs @@ -7,7 +7,7 @@ using System.IO; using System.Text; using Microsoft.AspNet.Http; using Microsoft.AspNet.Http.Internal; -using Microsoft.AspNet.Mvc.Abstractions; +using Microsoft.AspNet.Mvc.Controllers; using Microsoft.AspNet.Routing; #if MOCK_SUPPORT using Moq; @@ -154,10 +154,9 @@ namespace Microsoft.AspNet.Mvc var fileName = "Created.html"; var mockHttpContext = new Mock(); mockHttpContext.Setup(x => x.Response.RegisterForDispose(It.IsAny())); - var controller = new TestabilityController() - { - ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()) - }; + + var controller = new TestabilityController(); + controller.ControllerContext.HttpContext = mockHttpContext.Object; // Act var result = controller.FileStream_Action(content, contentType, fileName); @@ -488,38 +487,38 @@ namespace Microsoft.AspNet.Mvc var controller = new TestabilityController(); // Assert - Assert.NotNull(controller.ActionContext); - Assert.NotNull(controller.ActionContext.ModelState); - Assert.Null(controller.ActionContext.ActionDescriptor); - Assert.Null(controller.ActionContext.HttpContext); - Assert.Null(controller.ActionContext.RouteData); + Assert.NotNull(controller.ControllerContext); + Assert.NotNull(controller.ControllerContext.ModelState); + Assert.Null(controller.ControllerContext.ActionDescriptor); + Assert.Null(controller.ControllerContext.HttpContext); + Assert.Null(controller.ControllerContext.RouteData); } [Fact] - public void ActionContextDefaultConstructor_CanBeUsedForControllerActionContext() + public void ContextDefaultConstructor_CanBeUsedForControllerContext() { // Arrange - var actionContext = new ActionContext(); + var controllerContext = new ControllerContext(); var controller = new TestabilityController(); // Act - controller.ActionContext = actionContext; + controller.ControllerContext = controllerContext; // Assert - Assert.Equal(actionContext.HttpContext, controller.HttpContext); - Assert.Equal(actionContext.RouteData, controller.RouteData); - Assert.Equal(actionContext.ModelState, controller.ModelState); + Assert.Equal(controllerContext.HttpContext, controller.HttpContext); + Assert.Equal(controllerContext.RouteData, controller.RouteData); + Assert.Equal(controllerContext.ModelState, controller.ModelState); } [Fact] - public void ActionContextSetters_CanBeUsedWithControllerActionContext() + public void ControllerContextSetter_CanBeUsedWithControllerActionContext() { // Arrange - var actionDescriptor = new ActionDescriptor(); + var actionDescriptor = new ControllerActionDescriptor(); var httpContext = new DefaultHttpContext(); var routeData = new RouteData(); - var actionContext = new ActionContext() + var controllerContext = new ControllerContext() { ActionDescriptor = actionDescriptor, HttpContext = httpContext, @@ -529,33 +528,32 @@ namespace Microsoft.AspNet.Mvc var controller = new TestabilityController(); // Act - controller.ActionContext = actionContext; + controller.ControllerContext = controllerContext; // Assert Assert.Same(httpContext, controller.HttpContext); Assert.Same(routeData, controller.RouteData); - Assert.Equal(actionContext.ModelState, controller.ModelState); - Assert.Same(actionDescriptor, actionContext.ActionDescriptor); + Assert.Equal(controllerContext.ModelState, controller.ModelState); + Assert.Same(actionDescriptor, controllerContext.ActionDescriptor); } [Fact] - public void ActionContextModelState_ShouldBeSameAsViewDataAndControllerModelState() + public void ContextModelState_ShouldBeSameAsViewDataAndControllerModelState() { // Arrange - var actionContext = new ActionContext(); var controller1 = new TestabilityController(); var controller2 = new TestabilityController(); // Act - controller2.ActionContext = actionContext; + controller2.ControllerContext = new ControllerContext(); // Assert - Assert.Equal(controller1.ModelState, controller1.ActionContext.ModelState); + Assert.Equal(controller1.ModelState, controller1.ControllerContext.ModelState); Assert.Equal(controller1.ModelState, controller1.ViewData.ModelState); - Assert.Equal(actionContext.ModelState, controller2.ModelState); - Assert.Equal(actionContext.ModelState, controller2.ActionContext.ModelState); - Assert.Equal(actionContext.ModelState, controller2.ViewData.ModelState); + Assert.Equal(controller1.ControllerContext.ModelState, controller2.ModelState); + Assert.Equal(controller1.ControllerContext.ModelState, controller2.ControllerContext.ModelState); + Assert.Equal(controller1.ControllerContext.ModelState, controller2.ViewData.ModelState); } [Fact] diff --git a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ApiControllerTest.cs b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ApiControllerTest.cs index 483e434b62..c2fe8834f1 100644 --- a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ApiControllerTest.cs +++ b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ApiControllerTest.cs @@ -9,7 +9,7 @@ using System.Text; using Microsoft.AspNet.Http; using Microsoft.AspNet.Http.Internal; using Microsoft.AspNet.Mvc; -using Microsoft.AspNet.Mvc.Abstractions; +using Microsoft.AspNet.Mvc.Controllers; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Routing; using Newtonsoft.Json; @@ -27,12 +27,11 @@ namespace System.Web.Http var httpContext = new DefaultHttpContext(); httpContext.User = new ClaimsPrincipal(); - - var routeContext = new RouteContext(httpContext); - var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); + + var actionContext = new ActionContext(httpContext, new RouteData(), new ControllerActionDescriptor()); // Act - controller.ActionContext = actionContext; + controller.ControllerContext = new ControllerContext(actionContext); // Assert Assert.Same(httpContext, controller.Context); @@ -48,7 +47,7 @@ namespace System.Web.Http // Act & Assert Assert.Null(controller.Context); - Assert.Null(controller.ModelState); + Assert.NotNull(controller.ModelState); Assert.Null(controller.User); } diff --git a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/BadRequestErrorMessageResultTest.cs b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/BadRequestErrorMessageResultTest.cs index 9158c77511..5627ce7e70 100644 --- a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/BadRequestErrorMessageResultTest.cs +++ b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/BadRequestErrorMessageResultTest.cs @@ -76,7 +76,6 @@ namespace System.Web.Http var services = new ServiceCollection(); services.AddSingleton(new ObjectResultExecutor( options, - new ActionBindingContextAccessor(), new TestHttpResponseStreamWriterFactory(), NullLoggerFactory.Instance)); diff --git a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ExceptionResultTest.cs b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ExceptionResultTest.cs index 5c1322eec8..479a3bf215 100644 --- a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ExceptionResultTest.cs +++ b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ExceptionResultTest.cs @@ -74,7 +74,6 @@ namespace System.Web.Http var services = new ServiceCollection(); services.AddSingleton(new ObjectResultExecutor( options, - new ActionBindingContextAccessor(), new TestHttpResponseStreamWriterFactory(), NullLoggerFactory.Instance)); diff --git a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/InvalidModelStateResultTest.cs b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/InvalidModelStateResultTest.cs index 0807ff1d73..24ff0a3801 100644 --- a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/InvalidModelStateResultTest.cs +++ b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/InvalidModelStateResultTest.cs @@ -87,7 +87,6 @@ namespace System.Web.Http var services = new ServiceCollection(); services.AddSingleton(new ObjectResultExecutor( options, - new ActionBindingContextAccessor(), new TestHttpResponseStreamWriterFactory(), NullLoggerFactory.Instance)); diff --git a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/NegotiatedContentResultTest.cs b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/NegotiatedContentResultTest.cs index d266885246..622c220a71 100644 --- a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/NegotiatedContentResultTest.cs +++ b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/NegotiatedContentResultTest.cs @@ -74,7 +74,6 @@ namespace System.Web.Http var services = new ServiceCollection(); services.AddSingleton(new ObjectResultExecutor( options, - new ActionBindingContextAccessor(), new TestHttpResponseStreamWriterFactory(), NullLoggerFactory.Instance)); diff --git a/test/WebSites/ApplicationModelWebSite/Controllers/ActionModelController.cs b/test/WebSites/ApplicationModelWebSite/Controllers/ActionModelController.cs index fd545b6d4c..a9279f0a75 100644 --- a/test/WebSites/ApplicationModelWebSite/Controllers/ActionModelController.cs +++ b/test/WebSites/ApplicationModelWebSite/Controllers/ActionModelController.cs @@ -4,7 +4,6 @@ using System; using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc.ApplicationModels; -using Microsoft.AspNet.Mvc.Controllers; namespace ApplicationModelWebSite { @@ -15,9 +14,7 @@ namespace ApplicationModelWebSite [ActionName2("ActionName")] public string GetActionName() { - var actionDescriptor = (ControllerActionDescriptor)ActionContext.ActionDescriptor; - - return actionDescriptor.Name; + return ControllerContext.ActionDescriptor.Name; } private class ActionName2Attribute : Attribute, IActionModelConvention diff --git a/test/WebSites/ApplicationModelWebSite/Controllers/ApplicationModelController.cs b/test/WebSites/ApplicationModelWebSite/Controllers/ApplicationModelController.cs index 47905046b9..6f2bfa7072 100644 --- a/test/WebSites/ApplicationModelWebSite/Controllers/ApplicationModelController.cs +++ b/test/WebSites/ApplicationModelWebSite/Controllers/ApplicationModelController.cs @@ -12,15 +12,13 @@ namespace ApplicationModelWebSite { public string GetControllerDescription() { - var actionDescriptor = (ControllerActionDescriptor)ActionContext.ActionDescriptor; - return actionDescriptor.Properties["description"].ToString(); + return ControllerContext.ActionDescriptor.Properties["description"].ToString(); } [ActionDescription("Specific Action Description")] public string GetActionSpecificDescription() { - var actionDescriptor = (ControllerActionDescriptor)ActionContext.ActionDescriptor; - return actionDescriptor.Properties["description"].ToString(); + return ControllerContext.ActionDescriptor.Properties["description"].ToString(); } } } \ No newline at end of file diff --git a/test/WebSites/ApplicationModelWebSite/Controllers/ControllerModelController.cs b/test/WebSites/ApplicationModelWebSite/Controllers/ControllerModelController.cs index 89f575e58f..25552ba464 100644 --- a/test/WebSites/ApplicationModelWebSite/Controllers/ControllerModelController.cs +++ b/test/WebSites/ApplicationModelWebSite/Controllers/ControllerModelController.cs @@ -15,9 +15,7 @@ namespace ApplicationModelWebSite { public string GetControllerName() { - var actionDescriptor = (ControllerActionDescriptor)ActionContext.ActionDescriptor; - - return actionDescriptor.ControllerName; + return ControllerContext.ActionDescriptor.ControllerName; } private class ControllerNameAttribute : Attribute, IControllerModelConvention diff --git a/test/WebSites/ApplicationModelWebSite/Controllers/HomeController.cs b/test/WebSites/ApplicationModelWebSite/Controllers/HomeController.cs index 96bd88b791..8a5892cc3a 100644 --- a/test/WebSites/ApplicationModelWebSite/Controllers/HomeController.cs +++ b/test/WebSites/ApplicationModelWebSite/Controllers/HomeController.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNet.Mvc; -using Microsoft.AspNet.Mvc.Controllers; namespace ApplicationModelWebSite { @@ -10,15 +9,13 @@ namespace ApplicationModelWebSite { public string GetCommonDescription() { - var actionDescriptor = (ControllerActionDescriptor)ActionContext.ActionDescriptor; - return actionDescriptor.Properties["description"].ToString(); + return ControllerContext.ActionDescriptor.Properties["description"].ToString(); } [HttpGet("Home/GetHelloWorld")] public object GetHelloWorld([FromHeader] string helloWorld) { - var actionDescriptor = (ControllerActionDescriptor)ActionContext.ActionDescriptor; - return actionDescriptor.Properties["source"].ToString() + " - " + helloWorld; + return ControllerContext.ActionDescriptor.Properties["source"].ToString() + " - " + helloWorld; } } } \ No newline at end of file diff --git a/test/WebSites/ApplicationModelWebSite/Controllers/LisenceController.cs b/test/WebSites/ApplicationModelWebSite/Controllers/LisenceController.cs index 5828eb6572..a074533f54 100644 --- a/test/WebSites/ApplicationModelWebSite/Controllers/LisenceController.cs +++ b/test/WebSites/ApplicationModelWebSite/Controllers/LisenceController.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNet.Mvc; -using Microsoft.AspNet.Mvc.Controllers; namespace ApplicationModelWebSite.Controllers { @@ -11,8 +10,7 @@ namespace ApplicationModelWebSite.Controllers [HttpGet("Lisence/GetLisence")] public string GetLisence() { - var actionDescriptor = (ControllerActionDescriptor)ActionContext.ActionDescriptor; - return actionDescriptor.Properties["lisence"].ToString(); + return ControllerContext.ActionDescriptor.Properties["lisence"].ToString(); } } } \ No newline at end of file diff --git a/test/WebSites/ApplicationModelWebSite/Controllers/ParameterModelController.cs b/test/WebSites/ApplicationModelWebSite/Controllers/ParameterModelController.cs index 0fce443494..e167f0a05e 100644 --- a/test/WebSites/ApplicationModelWebSite/Controllers/ParameterModelController.cs +++ b/test/WebSites/ApplicationModelWebSite/Controllers/ParameterModelController.cs @@ -16,7 +16,7 @@ namespace ApplicationModelWebSite { public string GetParameterMetadata([Cool] int? id) { - return ActionContext.ActionDescriptor.Parameters[0].BindingInfo.BinderModelName; + return ControllerContext.ActionDescriptor.Parameters[0].BindingInfo.BinderModelName; } private class CoolAttribute : Attribute, IParameterModelConvention diff --git a/test/WebSites/BasicWebSite/Controllers/HomeController.cs b/test/WebSites/BasicWebSite/Controllers/HomeController.cs index 86d1c1a39a..e169f34ddd 100644 --- a/test/WebSites/BasicWebSite/Controllers/HomeController.cs +++ b/test/WebSites/BasicWebSite/Controllers/HomeController.cs @@ -95,8 +95,7 @@ namespace BasicWebSite.Controllers public string GetApplicationDescription() { - var actionDescriptor = (ControllerActionDescriptor)ActionContext.ActionDescriptor; - return actionDescriptor.Properties["description"].ToString(); + return ControllerContext.ActionDescriptor.Properties["description"].ToString(); } } } \ No newline at end of file diff --git a/test/WebSites/BasicWebSite/Controllers/RoutingController.cs b/test/WebSites/BasicWebSite/Controllers/RoutingController.cs index f9705530ec..9950c0ac62 100644 --- a/test/WebSites/BasicWebSite/Controllers/RoutingController.cs +++ b/test/WebSites/BasicWebSite/Controllers/RoutingController.cs @@ -35,8 +35,8 @@ namespace BasicWebSite private object GetData() { - var routers = ActionContext.RouteData.Routers.Select(r => r.GetType().FullName).ToArray(); - var dataTokens = ActionContext.RouteData.DataTokens; + var routers = RouteData.Routers.Select(r => r.GetType().FullName).ToArray(); + var dataTokens = RouteData.DataTokens; return new { diff --git a/test/WebSites/BasicWebSite/Controllers/SpecificFormattersController.cs b/test/WebSites/BasicWebSite/Controllers/SpecificFormattersController.cs index 1cadb3e0fe..dc0de3896e 100644 --- a/test/WebSites/BasicWebSite/Controllers/SpecificFormattersController.cs +++ b/test/WebSites/BasicWebSite/Controllers/SpecificFormattersController.cs @@ -41,7 +41,7 @@ namespace BasicWebSite } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] - private class CamelCaseJsonFormattersAttribute : Attribute, IResourceFilter + private class CamelCaseJsonFormattersAttribute : Attribute, IResourceFilter, IResultFilter { private readonly JsonSerializerSettings _serializerSettings; @@ -61,10 +61,22 @@ namespace BasicWebSite // Instead remove and add new formatters which only effects the controllers this // attribute is decorated on. context.InputFormatters.RemoveType(); - context.OutputFormatters.RemoveType(); - context.InputFormatters.Add(new JsonInputFormatter(_serializerSettings)); - context.OutputFormatters.Add(new JsonOutputFormatter(_serializerSettings)); + + } + + public void OnResultExecuted(ResultExecutedContext context) + { + } + + public void OnResultExecuting(ResultExecutingContext context) + { + var objectResult = context.Result as ObjectResult; + if (objectResult != null) + { + objectResult.Formatters.RemoveType(); + objectResult.Formatters.Add(new JsonOutputFormatter(_serializerSettings)); + } } } } diff --git a/test/WebSites/ContentNegotiationWebSite/Controllers/FallbackOnTypeBasedMatchController.cs b/test/WebSites/ContentNegotiationWebSite/Controllers/FallbackOnTypeBasedMatchController.cs index 74401d43a9..ac193b4e71 100644 --- a/test/WebSites/ContentNegotiationWebSite/Controllers/FallbackOnTypeBasedMatchController.cs +++ b/test/WebSites/ContentNegotiationWebSite/Controllers/FallbackOnTypeBasedMatchController.cs @@ -52,7 +52,7 @@ namespace ContentNegotiationWebSite public IActionResult OverrideTheFallback_WithDefaultFormatters(int input) { var objectResult = new ObjectResult(input); - var optionsAccessor = ActionContext.HttpContext.RequestServices + var optionsAccessor = HttpContext.RequestServices .GetRequiredService>(); objectResult.Formatters.Add(new HttpNotAcceptableOutputFormatter()); foreach (var formatter in optionsAccessor.Value.OutputFormatters) diff --git a/test/WebSites/CustomRouteWebSite/Controllers/CustomRoute_OrdersControlller.cs b/test/WebSites/CustomRouteWebSite/Controllers/CustomRoute_OrdersControlller.cs index b4690478ad..c6547b032e 100644 --- a/test/WebSites/CustomRouteWebSite/Controllers/CustomRoute_OrdersControlller.cs +++ b/test/WebSites/CustomRouteWebSite/Controllers/CustomRoute_OrdersControlller.cs @@ -10,7 +10,7 @@ namespace CustomRouteWebSite.Controllers [HttpGet("CustomRoute_Orders/{id}")] public string Index(int id) { - return "Hello from " + ActionContext.RouteData.Values["locale"] + "."; + return "Hello from " + RouteData.Values["locale"] + "."; } } } diff --git a/test/WebSites/FiltersWebSite/Controllers/JsonOnlyController.cs b/test/WebSites/FiltersWebSite/Controllers/JsonOnlyController.cs index 7a7e5ebac6..032c679201 100644 --- a/test/WebSites/FiltersWebSite/Controllers/JsonOnlyController.cs +++ b/test/WebSites/FiltersWebSite/Controllers/JsonOnlyController.cs @@ -6,6 +6,8 @@ using System.Linq; using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc.Filters; using Microsoft.AspNet.Mvc.Formatters; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.OptionsModel; namespace FiltersWebSite.Controllers { @@ -19,7 +21,7 @@ namespace FiltersWebSite.Controllers return (dummy?.SampleInt ?? 0).ToString(); } - private class JsonOnlyAttribute : Attribute, IResourceFilter + private class JsonOnlyAttribute : Attribute, IResultFilter { public void OnResourceExecuted(ResourceExecutedContext context) { @@ -28,17 +30,26 @@ namespace FiltersWebSite.Controllers public void OnResourceExecuting(ResourceExecutingContext context) { // InputFormatters collection contains JsonInputFormatter and JsonPatchInputFormatter. Picking - // JsonInputFormatter by matching the typename + // JsonInputFormatter by matching the type exactly rather than using OfType. var jsonFormatter = context.InputFormatters.OfType() .Where(t => t.GetType() == typeof(JsonInputFormatter)).FirstOrDefault(); context.InputFormatters.Clear(); context.InputFormatters.Add(jsonFormatter); + } + + public void OnResultExecuted(ResultExecutedContext context) + { + } + + public void OnResultExecuting(ResultExecutingContext context) + { + var options = context.HttpContext.RequestServices.GetRequiredService>(); + var jsonFormatter = options.Value.OutputFormatters.OfType().Single(); // Update the output formatter collection to only return JSON. - var jsonOutputFormatter = context.OutputFormatters.OfType().Single(); - context.OutputFormatters.Clear(); - context.OutputFormatters.Add(jsonOutputFormatter); + var result = (ObjectResult)context.Result; + result.Formatters.Add(jsonFormatter); } } } diff --git a/test/WebSites/FormatterWebSite/Controllers/InputFormatterController.cs b/test/WebSites/FormatterWebSite/Controllers/InputFormatterController.cs index 27a9369524..4444196b96 100644 --- a/test/WebSites/FormatterWebSite/Controllers/InputFormatterController.cs +++ b/test/WebSites/FormatterWebSite/Controllers/InputFormatterController.cs @@ -12,11 +12,10 @@ namespace FormatterWebSite.Controllers [HttpPost] public object ActionHandlesError([FromBody] DummyClass dummy) { - if (!ActionContext.ModelState.IsValid) + if (!ModelState.IsValid) { // Body model binder normally reports errors for parameters using the empty name. - var parameterBindingErrors = ActionContext.ModelState["dummy"]?.Errors ?? - ActionContext.ModelState[string.Empty]?.Errors; + var parameterBindingErrors = ModelState["dummy"]?.Errors ?? ModelState[string.Empty]?.Errors; if (parameterBindingErrors != null && parameterBindingErrors.Count != 0) { return new ErrorInfo diff --git a/test/WebSites/InlineConstraintsWebSite/Controllers/ProductsController.cs b/test/WebSites/InlineConstraintsWebSite/Controllers/ProductsController.cs index f290dd9a03..0d0135eafe 100644 --- a/test/WebSites/InlineConstraintsWebSite/Controllers/ProductsController.cs +++ b/test/WebSites/InlineConstraintsWebSite/Controllers/ProductsController.cs @@ -13,60 +13,60 @@ namespace InlineConstraintsWebSite.Controllers { public IDictionary Index() { - return ActionContext.RouteData.Values; + return RouteData.Values; } [HttpGet("{id:int?}")] public IDictionary GetProductById(int id) { - return ActionContext.RouteData.Values; + return RouteData.Values; } [HttpGet("{name:alpha}")] public IDictionary GetProductByName(string name) { - return ActionContext.RouteData.Values; + return RouteData.Values; } [HttpGet("{dateTime:datetime}")] public IDictionary GetProductByManufacturingDate(DateTime dateTime) { - return ActionContext.RouteData.Values; + return RouteData.Values; } [HttpGet("{name:length(1,20)?}")] public IDictionary GetProductByCategoryName(string name) { - return ActionContext.RouteData.Values; + return RouteData.Values; } [HttpGet("{catId:int:range(10, 100)}")] public IDictionary GetProductByCategoryId(int catId) { - return ActionContext.RouteData.Values; + return RouteData.Values; } [HttpGet("{price:float?}")] public IDictionary GetProductByPrice(float price) { - return ActionContext.RouteData.Values; + return RouteData.Values; } [HttpGet("{manId:int:min(10)?}")] public IDictionary GetProductByManufacturerId(int manId) { - return ActionContext.RouteData.Values; + return RouteData.Values; } [HttpGet(@"{name:regex(^abc$)}")] public IDictionary GetUserByName(string name) { - return ActionContext.RouteData.Values; + return RouteData.Values; } public string GetGeneratedLink() { - var query = ActionContext.HttpContext.Request.Query; + var query = HttpContext.Request.Query; var values = query .Where(kvp => kvp.Key != "newAction" && kvp.Key != "newController") .ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value[0]); diff --git a/test/WebSites/InlineConstraintsWebSite/Controllers/StoreController.cs b/test/WebSites/InlineConstraintsWebSite/Controllers/StoreController.cs index a5645ae61e..c3b2accff7 100644 --- a/test/WebSites/InlineConstraintsWebSite/Controllers/StoreController.cs +++ b/test/WebSites/InlineConstraintsWebSite/Controllers/StoreController.cs @@ -11,12 +11,12 @@ namespace InlineConstraintsWebSite.Controllers { public IDictionary GetStoreById(Guid id) { - return ActionContext.RouteData.Values; + return RouteData.Values; } public IDictionary GetStoreByLocation(string location) { - return ActionContext.RouteData.Values; + return RouteData.Values; } } } \ No newline at end of file diff --git a/test/WebSites/ModelBindingWebSite/Controllers/HomeController.cs b/test/WebSites/ModelBindingWebSite/Controllers/HomeController.cs index 70f2d402cd..1440fb1c04 100644 --- a/test/WebSites/ModelBindingWebSite/Controllers/HomeController.cs +++ b/test/WebSites/ModelBindingWebSite/Controllers/HomeController.cs @@ -47,12 +47,12 @@ namespace ModelBindingWebSite.Controllers public bool ActionWithCancellationToken(CancellationToken token) { - return token == ActionContext.HttpContext.RequestAborted; + return token == HttpContext.RequestAborted; } public bool ActionWithCancellationTokenModel(CancellationTokenModel wrapper) { - return wrapper.CancellationToken == ActionContext.HttpContext.RequestAborted; + return wrapper.CancellationToken == HttpContext.RequestAborted; } [HttpGet("Home/ActionWithPersonFromUrlWithPrefix/{person.name}/{person.age}")] diff --git a/test/WebSites/ModelBindingWebSite/Controllers/RoundtripController.cs b/test/WebSites/ModelBindingWebSite/Controllers/RoundtripController.cs index 38f0b9781f..55bb6e5888 100644 --- a/test/WebSites/ModelBindingWebSite/Controllers/RoundtripController.cs +++ b/test/WebSites/ModelBindingWebSite/Controllers/RoundtripController.cs @@ -32,7 +32,7 @@ namespace ModelBindingWebSite.Controllers _activated = true; var viewData = new ViewDataDictionary(ViewData); var context = new ViewContext( - ActionContext, + ControllerContext, new TestView(), viewData, TempData, diff --git a/test/WebSites/ValueProvidersWebSite/CustomValueProviderFactory.cs b/test/WebSites/ValueProvidersWebSite/CustomValueProviderFactory.cs index d4b87904a0..8f7d9b16a1 100644 --- a/test/WebSites/ValueProvidersWebSite/CustomValueProviderFactory.cs +++ b/test/WebSites/ValueProvidersWebSite/CustomValueProviderFactory.cs @@ -4,13 +4,14 @@ using System; using System.Globalization; using System.Threading.Tasks; +using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc.ModelBinding; namespace ValueProvidersWebSite { public class CustomValueProviderFactory : IValueProviderFactory { - public Task GetValueProviderAsync(ValueProviderFactoryContext context) + public Task GetValueProviderAsync(ActionContext context) { if (context.HttpContext.Request.Path.Value.Contains("TestValueProvider")) {