Updating ActionContext for the default constructor and the setter methods

This commit is contained in:
Youngjune Hong 2015-02-03 10:19:36 -08:00
parent 2e938a51f8
commit 57c04835de
4 changed files with 156 additions and 18 deletions

View File

@ -12,6 +12,17 @@ namespace Microsoft.AspNet.Mvc
/// </summary>
public class ActionContext
{
/// <summary>
/// Creates a empty <see cref="ActionContext"/>.
/// </summary>
/// <remarks>
/// The default constructor is provided for unit test purposes only.
/// </remarks>
public ActionContext()
{
ModelState = new ModelStateDictionary();
}
/// <summary>
/// Creates a new <see cref="ActionContext"/>.
/// </summary>
@ -56,23 +67,44 @@ namespace Microsoft.AspNet.Mvc
}
/// <summary>
/// Gets the <see cref="Mvc.ActionDescriptor"/> for the selected action.
/// Gets or sets the <see cref="Mvc.ActionDescriptor"/> for the selected action.
/// </summary>
public ActionDescriptor ActionDescriptor { get; }
/// <remarks>
/// The property setter is provided for unit test purposes only.
/// </remarks>
public ActionDescriptor ActionDescriptor
{
get; set;
}
/// <summary>
/// Gets the <see cref="Http.HttpContext"/> for the current request.
/// Gets or sets the <see cref="Http.HttpContext"/> for the current request.
/// </summary>
public HttpContext HttpContext { get; }
/// <remarks>
/// The property setter is provided for unit test purposes only.
/// </remarks>
public HttpContext HttpContext
{
get; set;
}
/// <summary>
/// Gets the <see cref="ModelStateDictionary"/>.
/// </summary>
public ModelStateDictionary ModelState { get; }
public ModelStateDictionary ModelState
{
get;
}
/// <summary>
/// Gets the <see cref="AspNet.Routing.RouteData"/> for the current request.
/// Gets or sets the <see cref="AspNet.Routing.RouteData"/> for the current request.
/// </summary>
public RouteData RouteData { get; }
/// <remarks>
/// The property setter is provided for unit test purposes only.
/// </remarks>
public RouteData RouteData
{
get; set;
}
}
}
}

View File

@ -20,6 +20,7 @@ namespace Microsoft.AspNet.Mvc
{
private DynamicViewData _viewBag;
private ViewDataDictionary _viewData;
private ActionContext _actionContext;
public IServiceProvider Resolver
{
@ -69,8 +70,32 @@ namespace Microsoft.AspNet.Mvc
}
}
/// <summary>
/// Gets or sets the <see cref="Mvc.ActionContext"/> object.
/// </summary>
/// <remarks>
/// <see cref="IControllerActivator"/> activates this property while activating controllers. If user codes
/// directly instantiate controllers, the getter returns an empty <see cref="Mvc.ActionContext"/>.
/// </remarks>
[Activate]
public ActionContext ActionContext { get; set; }
public ActionContext ActionContext
{
get
{
// This should run only for the controller unit test scenarios
_actionContext = _actionContext ?? new ActionContext();
return _actionContext;
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_actionContext = value;
}
}
[Activate]
public ActionBindingContext BindingContext { get; set; }
@ -822,7 +847,7 @@ namespace Microsoft.AspNet.Mvc
}
/// <summary>
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
/// </summary>
/// <typeparam name="TModel">The type of the model object.</typeparam>
@ -847,7 +872,7 @@ namespace Microsoft.AspNet.Mvc
}
/// <summary>
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
/// <paramref name="prefix"/>.
/// </summary>
/// <typeparam name="TModel">The type of the model object.</typeparam>
@ -882,14 +907,14 @@ namespace Microsoft.AspNet.Mvc
}
/// <summary>
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
/// </summary>
/// <typeparam name="TModel">The type of the model object.</typeparam>
/// <param name="model">The model instance to update.</param>
/// <param name="prefix">The prefix to use when looking up values in the current <see cref="IValueProvider"/>.
/// </param>
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
/// which need to be included for the current model.</param>
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
[NonAction]
@ -920,7 +945,7 @@ namespace Microsoft.AspNet.Mvc
}
/// <summary>
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
/// </summary>
/// <typeparam name="TModel">The type of the model object.</typeparam>
@ -957,7 +982,7 @@ namespace Microsoft.AspNet.Mvc
}
/// <summary>
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
/// <paramref name="prefix"/>.
/// </summary>
/// <typeparam name="TModel">The type of the model object.</typeparam>
@ -965,7 +990,7 @@ namespace Microsoft.AspNet.Mvc
/// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>
/// </param>
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
/// which need to be included for the current model.</param>
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
[NonAction]
@ -997,7 +1022,7 @@ namespace Microsoft.AspNet.Mvc
}
/// <summary>
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
/// <paramref name="prefix"/>.
/// </summary>
/// <typeparam name="TModel">The type of the model object.</typeparam>

View File

@ -1277,7 +1277,7 @@ namespace Microsoft.AspNet.Mvc.Test
var binder = new Mock<IModelBinder>();
var controller = GetController(binder.Object, provider: null);
controller.BindingContext.ValidatorProvider = provider.Object;
// Act
var result = controller.TryValidateModel(model, "Prefix");

View File

@ -5,7 +5,11 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.WebUtilities;
using Moq;
using Xunit;
namespace Microsoft.AspNet.Mvc
@ -424,6 +428,83 @@ namespace Microsoft.AspNet.Mvc
Assert.Throws<ArgumentException>(() => controller.Redirect_Action(null));
}
[Fact]
public void ControllerActionContext_ReturnsNotNull()
{
// Arrange && Act
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);
}
[Fact]
public void ActionContextDefaultConstructor_CanBeUsedForControllerActionContext()
{
// Arrange
var actionContext = new ActionContext();
var controller = new TestabilityController();
// Act
controller.ActionContext = actionContext;
// Assert
Assert.Equal(actionContext.HttpContext, controller.Context);
Assert.Equal(actionContext.RouteData, controller.RouteData);
Assert.Equal(actionContext.ModelState, controller.ModelState);
}
[Fact]
public void ActionContextSetters_CanBeUsedWithControllerActionContext()
{
// Arrange
var actionDescriptor = new Mock<ActionDescriptor>();
var httpContext = new Mock<HttpContext>();
var routeData = new Mock<RouteData>();
var actionContext = new ActionContext()
{
ActionDescriptor = actionDescriptor.Object,
HttpContext = httpContext.Object,
RouteData = routeData.Object,
};
var controller = new TestabilityController();
// Act
controller.ActionContext = actionContext;
// Assert
Assert.Equal(httpContext.Object, controller.Context);
Assert.Equal(routeData.Object, controller.RouteData);
Assert.Equal(actionContext.ModelState, controller.ModelState);
Assert.Equal(actionDescriptor.Object, actionContext.ActionDescriptor);
}
[Fact]
public void ActionContextModelState_ShouldBeSameAsViewDataAndControllerModelState()
{
// Arrange
var actionContext = new ActionContext();
var controller1 = new Controller();
var controller2 = new Controller();
// Act
controller2.ActionContext = actionContext;
// Assert
Assert.Equal(controller1.ModelState, controller1.ActionContext.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);
}
public static IEnumerable<object[]> TestabilityViewTestData
{
get