WebFX 156: Adding support for RedirectToAction and RedirectToRoute
This commit is contained in:
parent
1536daa107
commit
ecd8ddeae4
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class RedirectToActionResult : IActionResult
|
||||
{
|
||||
public RedirectToActionResult([NotNull] IUrlHelper urlHelper, string actionName,
|
||||
string controllerName, IDictionary<string, object> routeValues)
|
||||
: this(urlHelper, actionName, controllerName, routeValues, permanent: false)
|
||||
{
|
||||
}
|
||||
|
||||
public RedirectToActionResult([NotNull] IUrlHelper urlHelper, string actionName,
|
||||
string controllerName, IDictionary<string, object> routeValues, bool permanent)
|
||||
{
|
||||
UrlHelper = urlHelper;
|
||||
ActionName = actionName;
|
||||
ControllerName = controllerName;
|
||||
RouteValues = routeValues;
|
||||
Permanent = permanent;
|
||||
}
|
||||
|
||||
public IUrlHelper UrlHelper { get; private set; }
|
||||
|
||||
public string ActionName { get; private set; }
|
||||
|
||||
public string ControllerName { get; private set; }
|
||||
|
||||
public IDictionary<string, object> RouteValues { get; private set; }
|
||||
|
||||
public bool Permanent { get; private set; }
|
||||
|
||||
public async Task ExecuteResultAsync([NotNull] ActionContext context)
|
||||
{
|
||||
var destinationUrl = UrlHelper.Action(ActionName, ControllerName, RouteValues);
|
||||
|
||||
if (string.IsNullOrEmpty(destinationUrl))
|
||||
{
|
||||
throw new InvalidOperationException(Resources.NoRoutesMatched);
|
||||
}
|
||||
|
||||
context.HttpContext.Response.Redirect(destinationUrl, Permanent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class RedirectToRouteResult : IActionResult
|
||||
{
|
||||
public RedirectToRouteResult([NotNull] IUrlHelper urlHelper, IDictionary<string, object> routeValues)
|
||||
: this(urlHelper, routeValues, permanent: false)
|
||||
{
|
||||
}
|
||||
|
||||
public RedirectToRouteResult([NotNull] IUrlHelper urlHelper,
|
||||
IDictionary<string, object> routeValues, bool permanent)
|
||||
{
|
||||
UrlHelper = urlHelper;
|
||||
RouteValues = routeValues;
|
||||
Permanent = permanent;
|
||||
}
|
||||
|
||||
public IUrlHelper UrlHelper { get; private set; }
|
||||
|
||||
public IDictionary<string, object> RouteValues { get; private set; }
|
||||
|
||||
public bool Permanent { get; private set; }
|
||||
|
||||
public async Task ExecuteResultAsync([NotNull] ActionContext context)
|
||||
{
|
||||
var destinationUrl = UrlHelper.RouteUrl(RouteValues);
|
||||
|
||||
if (string.IsNullOrEmpty(destinationUrl))
|
||||
{
|
||||
throw new InvalidOperationException(Resources.NoRoutesMatched);
|
||||
}
|
||||
|
||||
context.HttpContext.Response.Redirect(destinationUrl, Permanent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -119,5 +119,59 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
return new RedirectResult(url, permanent: true);
|
||||
}
|
||||
|
||||
public RedirectToActionResult RedirectToAction(string actionName)
|
||||
{
|
||||
return RedirectToAction(actionName, routeValues: null);
|
||||
}
|
||||
|
||||
public RedirectToActionResult RedirectToAction(string actionName, object routeValues)
|
||||
{
|
||||
return RedirectToAction(actionName, controllerName: null, routeValues: routeValues);
|
||||
}
|
||||
|
||||
public RedirectToActionResult RedirectToAction(string actionName, string controllerName)
|
||||
{
|
||||
return RedirectToAction(actionName, controllerName, routeValues: null);
|
||||
}
|
||||
|
||||
public RedirectToActionResult RedirectToAction(string actionName, string controllerName,
|
||||
object routeValues)
|
||||
{
|
||||
return new RedirectToActionResult(Url, actionName, controllerName,
|
||||
TypeHelper.ObjectToDictionary(routeValues));
|
||||
}
|
||||
|
||||
public RedirectToActionResult RedirectToActionPermanent(string actionName)
|
||||
{
|
||||
return RedirectToActionPermanent(actionName, routeValues: null);
|
||||
}
|
||||
|
||||
public RedirectToActionResult RedirectToActionPermanent(string actionName, object routeValues)
|
||||
{
|
||||
return RedirectToActionPermanent(actionName, controllerName: null, routeValues: routeValues);
|
||||
}
|
||||
|
||||
public RedirectToActionResult RedirectToActionPermanent(string actionName, string controllerName)
|
||||
{
|
||||
return RedirectToActionPermanent(actionName, controllerName, routeValues: null);
|
||||
}
|
||||
|
||||
public RedirectToActionResult RedirectToActionPermanent(string actionName, string controllerName,
|
||||
object routeValues)
|
||||
{
|
||||
return new RedirectToActionResult(Url, actionName, controllerName,
|
||||
TypeHelper.ObjectToDictionary(routeValues), permanent: true);
|
||||
}
|
||||
|
||||
public RedirectToRouteResult RedirectToRoute(object routeValues)
|
||||
{
|
||||
return new RedirectToRouteResult(Url, TypeHelper.ObjectToDictionary(routeValues));
|
||||
}
|
||||
|
||||
public RedirectToRouteResult RedirectToRoutePermanent(object routeValues)
|
||||
{
|
||||
return new RedirectToRouteResult(Url, TypeHelper.ObjectToDictionary(routeValues), permanent: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -538,6 +538,22 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
return string.Format(CultureInfo.CurrentCulture, GetString("ViewData_WrongTModelType"), p0, p1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No route matches the supplied values.
|
||||
/// </summary>
|
||||
internal static string NoRoutesMatched
|
||||
{
|
||||
get { return GetString("NoRoutesMatched"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No route matches the supplied values.
|
||||
/// </summary>
|
||||
internal static string FormatNoRoutesMatched()
|
||||
{
|
||||
return GetString("NoRoutesMatched");
|
||||
}
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -216,4 +216,7 @@
|
|||
<data name="ViewData_WrongTModelType" xml:space="preserve">
|
||||
<value>The model item passed into the ViewDataDictionary is of type '{0}', but this ViewDataDictionary instance requires a model item of type '{1}'.</value>
|
||||
</data>
|
||||
<data name="NoRoutesMatched" xml:space="preserve">
|
||||
<value>No route matches the supplied values.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
|
||||
{
|
||||
public class RedirectToActionResultTest
|
||||
{
|
||||
[Fact]
|
||||
public async void RedirectToAction_Execute_PassesCorrectValuesToRedirect()
|
||||
{
|
||||
// Arrange
|
||||
var expectedUrl = "SampleAction";
|
||||
var expectedPermanentFlag = false;
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
var httpResponse = new Mock<HttpResponse>();
|
||||
httpContext.Setup(o => o.Response).Returns(httpResponse.Object);
|
||||
|
||||
var actionContext = new ActionContext(httpContext.Object,
|
||||
Mock.Of<IRouter>(),
|
||||
new Dictionary<string, object>(),
|
||||
new ActionDescriptor());
|
||||
IUrlHelper urlHelper = GetMockUrlHelper(expectedUrl);
|
||||
RedirectToActionResult result = new RedirectToActionResult(urlHelper, "SampleAction", null, null);
|
||||
|
||||
// Act
|
||||
await result.ExecuteResultAsync(actionContext);
|
||||
|
||||
// Assert
|
||||
// Verifying if Redirect was called with the specific Url and parameter flag.
|
||||
// Thus we verify that the Url returned by UrlHelper is passed properly to
|
||||
// Redirect method and that the method is called exactly once.
|
||||
httpResponse.Verify(r => r.Redirect(expectedUrl, expectedPermanentFlag), Times.Exactly(1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RedirectToAction_Execute_ThrowsOnNullUrl()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.Setup(o => o.Response).Returns(new Mock<HttpResponse>().Object);
|
||||
var actionContext = new ActionContext(httpContext.Object,
|
||||
Mock.Of<IRouter>(),
|
||||
new Dictionary<string, object>(),
|
||||
new ActionDescriptor());
|
||||
|
||||
IUrlHelper urlHelper = GetMockUrlHelper(returnValue: null);
|
||||
RedirectToActionResult result = new RedirectToActionResult(urlHelper, null, null, null);
|
||||
|
||||
// Act & Assert
|
||||
ExceptionAssert.ThrowsAsync<InvalidOperationException>(
|
||||
async () =>
|
||||
{
|
||||
await result.ExecuteResultAsync(actionContext);
|
||||
},
|
||||
"No route matches the supplied values.");
|
||||
}
|
||||
|
||||
private static IUrlHelper GetMockUrlHelper(string returnValue)
|
||||
{
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
urlHelper.Setup(o => o.Action(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<object>(),
|
||||
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(returnValue);
|
||||
|
||||
return urlHelper.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Core
|
||||
{
|
||||
public class RedirectToRouteResultTest
|
||||
{
|
||||
[Theory]
|
||||
[MemberData("RedirectToRouteData")]
|
||||
public async void RedirectToRoute_Execute_PassesCorrectValuesToRedirect(object values)
|
||||
{
|
||||
// Arrange
|
||||
var expectedUrl = "SampleAction";
|
||||
var expectedPermanentFlag = false;
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
var httpResponse = new Mock<HttpResponse>();
|
||||
httpContext.Setup(o => o.Response).Returns(httpResponse.Object);
|
||||
|
||||
var actionContext = new ActionContext(httpContext.Object,
|
||||
Mock.Of<IRouter>(),
|
||||
new Dictionary<string, object>(),
|
||||
new ActionDescriptor());
|
||||
IUrlHelper urlHelper = GetMockUrlHelper(expectedUrl);
|
||||
RedirectToRouteResult result = new RedirectToRouteResult(urlHelper, TypeHelper.ObjectToDictionary(values));
|
||||
|
||||
// Act
|
||||
await result.ExecuteResultAsync(actionContext);
|
||||
|
||||
// Assert
|
||||
// Verifying if Redirect was called with the specific Url and parameter flag.
|
||||
// Thus we verify that the Url returned by UrlHelper is passed properly to
|
||||
// Redirect method and that the method is called exactly once.
|
||||
httpResponse.Verify(r => r.Redirect(expectedUrl, expectedPermanentFlag), Times.Exactly(1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RedirectToRoute_Execute_ThrowsOnNullUrl()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.Setup(o => o.Response).Returns(new Mock<HttpResponse>().Object);
|
||||
var actionContext = new ActionContext(httpContext.Object,
|
||||
Mock.Of<IRouter>(),
|
||||
new Dictionary<string, object>(),
|
||||
new ActionDescriptor());
|
||||
|
||||
IUrlHelper urlHelper = GetMockUrlHelper(returnValue: null);
|
||||
RedirectToRouteResult result = new RedirectToRouteResult(urlHelper, new Dictionary<string, object>());
|
||||
|
||||
// Act & Assert
|
||||
ExceptionAssert.ThrowsAsync<InvalidOperationException>(
|
||||
async () =>
|
||||
{
|
||||
await result.ExecuteResultAsync(actionContext);
|
||||
},
|
||||
"No route matches the supplied values.");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> RedirectToRouteData
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new object[] { null };
|
||||
yield return
|
||||
new object[] {
|
||||
new Dictionary<string, string>() { { "hello", "world" } }
|
||||
};
|
||||
yield return
|
||||
new object[] {
|
||||
new RouteValueDictionary(new Dictionary<string, string>() {
|
||||
{ "test", "case" }, { "sample", "route" } })
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static IUrlHelper GetMockUrlHelper(string returnValue)
|
||||
{
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
urlHelper.Setup(o => o.RouteUrl(It.IsAny<object>(), It.IsAny<string>(),
|
||||
It.IsAny<string>(), It.IsAny<string>())).Returns(returnValue);
|
||||
return urlHelper.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -83,5 +84,182 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
ExceptionAssert.ThrowsArgument(
|
||||
() => controller.RedirectPermanent(url: url), "url", "The value cannot be null or empty");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RedirectToAction_Temporary_Returns_SameAction()
|
||||
{
|
||||
// Arrange
|
||||
var controller = new Controller();
|
||||
|
||||
// Act
|
||||
var resultTemporary = controller.RedirectToAction("SampleAction");
|
||||
|
||||
// Assert
|
||||
Assert.False(resultTemporary.Permanent);
|
||||
Assert.Equal("SampleAction", resultTemporary.ActionName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RedirectToAction_Permanent_Returns_SameAction()
|
||||
{
|
||||
// Arrange
|
||||
var controller = new Controller();
|
||||
|
||||
// Act
|
||||
var resultPermanent = controller.RedirectToActionPermanent("SampleAction");
|
||||
|
||||
// Assert
|
||||
Assert.True(resultPermanent.Permanent);
|
||||
Assert.Equal("SampleAction", resultPermanent.ActionName);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData(null)]
|
||||
[InlineData("SampleController")]
|
||||
public void RedirectToAction_Temporary_Returns_SameController(string controllerName)
|
||||
{
|
||||
// Arrange
|
||||
var controller = new Controller();
|
||||
|
||||
// Act
|
||||
var resultTemporary = controller.RedirectToAction("SampleAction", controllerName);
|
||||
|
||||
// Assert
|
||||
Assert.False(resultTemporary.Permanent);
|
||||
Assert.Equal("SampleAction", resultTemporary.ActionName);
|
||||
Assert.Equal(controllerName, resultTemporary.ControllerName);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData(null)]
|
||||
[InlineData("SampleController")]
|
||||
public void RedirectToAction_Permanent_Returns_SameController(string controllerName)
|
||||
{
|
||||
// Arrange
|
||||
var controller = new Controller();
|
||||
|
||||
// Act
|
||||
var resultPermanent = controller.RedirectToActionPermanent("SampleAction", controllerName);
|
||||
|
||||
// Assert
|
||||
Assert.True(resultPermanent.Permanent);
|
||||
Assert.Equal("SampleAction", resultPermanent.ActionName);
|
||||
Assert.Equal(controllerName, resultPermanent.ControllerName);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("RedirectTestData")]
|
||||
public void RedirectToAction_Temporary_Returns_SameActionControllerAndRouteValues(object routeValues)
|
||||
{
|
||||
// Arrange
|
||||
var controller = new Controller();
|
||||
|
||||
// Act
|
||||
var resultTemporary = controller.RedirectToAction("SampleAction", "SampleController", routeValues);
|
||||
|
||||
// Assert
|
||||
Assert.False(resultTemporary.Permanent);
|
||||
Assert.Equal("SampleAction", resultTemporary.ActionName);
|
||||
Assert.Equal("SampleController", resultTemporary.ControllerName);
|
||||
Assert.Equal(TypeHelper.ObjectToDictionary(routeValues), resultTemporary.RouteValues);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("RedirectTestData")]
|
||||
public void RedirectToAction_Permanent_Returns_SameActionControllerAndRouteValues(object routeValues)
|
||||
{
|
||||
// Arrange
|
||||
var controller = new Controller();
|
||||
|
||||
// Act
|
||||
var resultPermanent = controller.RedirectToActionPermanent("SampleAction", "SampleController", routeValues);
|
||||
|
||||
// Assert
|
||||
Assert.True(resultPermanent.Permanent);
|
||||
Assert.Equal("SampleAction", resultPermanent.ActionName);
|
||||
Assert.Equal("SampleController", resultPermanent.ControllerName);
|
||||
Assert.Equal(TypeHelper.ObjectToDictionary(routeValues), resultPermanent.RouteValues);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("RedirectTestData")]
|
||||
public void RedirectToAction_Temporary_Returns_SameActionAndRouteValues(object routeValues)
|
||||
{
|
||||
// Arrange
|
||||
var controller = new Controller();
|
||||
|
||||
// Act
|
||||
var resultTemporary = controller.RedirectToAction(actionName: null, routeValues: routeValues);
|
||||
|
||||
// Assert
|
||||
Assert.False(resultTemporary.Permanent);
|
||||
Assert.Null(resultTemporary.ActionName);
|
||||
Assert.Equal(TypeHelper.ObjectToDictionary(routeValues), resultTemporary.RouteValues);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("RedirectTestData")]
|
||||
public void RedirectToAction_Permanent_Returns_SameActionAndRouteValues(object routeValues)
|
||||
{
|
||||
// Arrange
|
||||
var controller = new Controller();
|
||||
|
||||
// Act
|
||||
var resultPermanent = controller.RedirectToActionPermanent(null, routeValues);
|
||||
|
||||
// Assert
|
||||
Assert.True(resultPermanent.Permanent);
|
||||
Assert.Null(resultPermanent.ActionName);
|
||||
Assert.Equal(TypeHelper.ObjectToDictionary(routeValues), resultPermanent.RouteValues);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("RedirectTestData")]
|
||||
public void RedirectToRoute_Temporary_Returns_SameRouteValues(object routeValues)
|
||||
{
|
||||
// Arrange
|
||||
var controller = new Controller();
|
||||
|
||||
// Act
|
||||
var resultTemporary = controller.RedirectToRoute(routeValues);
|
||||
|
||||
// Assert
|
||||
Assert.False(resultTemporary.Permanent);
|
||||
Assert.Equal(TypeHelper.ObjectToDictionary(routeValues), resultTemporary.RouteValues);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("RedirectTestData")]
|
||||
public void RedirectToRoute_Permanent_Returns_SameRouteValues(object routeValues)
|
||||
{
|
||||
// Arrange
|
||||
var controller = new Controller();
|
||||
|
||||
// Act
|
||||
var resultPermanent = controller.RedirectToRoutePermanent(routeValues);
|
||||
|
||||
// Assert
|
||||
Assert.True(resultPermanent.Permanent);
|
||||
Assert.Equal(TypeHelper.ObjectToDictionary(routeValues), resultPermanent.RouteValues);
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> RedirectTestData
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new object[] { null };
|
||||
yield return
|
||||
new object[] {
|
||||
new Dictionary<string, string>() { { "hello", "world" } }
|
||||
};
|
||||
yield return
|
||||
new object[] {
|
||||
new RouteValueDictionary(new Dictionary<string, string>() {
|
||||
{ "test", "case" }, { "sample", "route" } })
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue