From 7c8dd45b8b55e1e43155e3e73c9b0e8ab0607796 Mon Sep 17 00:00:00 2001 From: sornaks Date: Mon, 31 Mar 2014 14:56:50 -0700 Subject: [PATCH] WebFX 156 - Adding support for Redirect and RedirectPermanent --- .../ActionResults/RedirectResult.cs | 38 ++++++++++++ src/Microsoft.AspNet.Mvc.Core/Controller.cs | 24 +++++++- .../Properties/Resources.Designer.cs | 22 ++++++- src/Microsoft.AspNet.Mvc.Core/Resources.resx | 3 + .../ControllerTests.cs | 58 ++++++++++++++++++- 5 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectResult.cs diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectResult.cs new file mode 100644 index 0000000000..c9e6bf1ef5 --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectResult.cs @@ -0,0 +1,38 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNet.DependencyInjection; +using Microsoft.AspNet.Mvc.Core; + +namespace Microsoft.AspNet.Mvc +{ + public class RedirectResult : IActionResult + { + public RedirectResult(string url) + : this(url, permanent: false) + { + } + + public RedirectResult(string url, bool permanent) + { + if (string.IsNullOrEmpty(url)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, "url"); + } + + Permanent = permanent; + Url = url; + } + + public bool Permanent { get; private set; } + + public string Url { get; private set; } + + public async Task ExecuteResultAsync([NotNull] ActionContext context) + { + // It is redirected directly to the input URL. + // We would use the context to construct the full URL, + // only when relative URLs are supported. (Issue - WEBFX-202) + context.HttpContext.Response.Redirect(Url, Permanent); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Core/Controller.cs b/src/Microsoft.AspNet.Mvc.Core/Controller.cs index 14584a8afe..f652bc911a 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Controller.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Controller.cs @@ -1,5 +1,7 @@ -using System.Text; +using System; +using System.Text; using Microsoft.AspNet.Abstractions; +using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.Rendering; @@ -97,5 +99,25 @@ namespace Microsoft.AspNet.Mvc { return Result.Json(value); } + + public virtual RedirectResult Redirect(string url) + { + if (string.IsNullOrEmpty(url)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, "url"); + } + + return new RedirectResult(url); + } + + public virtual RedirectResult RedirectPermanent(string url) + { + if (string.IsNullOrEmpty(url)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, "url"); + } + + return new RedirectResult(url, permanent: true); + } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs index 862d4280d6..a81a357d42 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs @@ -250,6 +250,22 @@ namespace Microsoft.AspNet.Mvc.Core return string.Format(CultureInfo.CurrentCulture, GetString("DefaultControllerFactory_ActionDescriptorMustBeReflected"), p0); } + /// + /// The value cannot be null or empty. + /// + internal static string ArgumentCannotBeNullOrEmpty + { + get { return GetString("ArgumentCannotBeNullOrEmpty"); } + } + + /// + /// The value cannot be null or empty. + /// + internal static string FormatArgumentCannotBeNullOrEmpty() + { + return GetString("ArgumentCannotBeNullOrEmpty"); + } + /// /// The '{0}' property of '{1}' must not be null. /// @@ -267,7 +283,7 @@ namespace Microsoft.AspNet.Mvc.Core } /// - /// The '{0}' must return a non null '{1}'. + /// The '{0}' must return a non-null '{1}'. /// internal static string MethodMustReturnNotNullValue { @@ -275,7 +291,7 @@ namespace Microsoft.AspNet.Mvc.Core } /// - /// The '{0}' must return a non null '{1}'. + /// The '{0}' must return a non-null '{1}'. /// internal static string FormatMethodMustReturnNotNullValue(object p0, object p1) { @@ -287,7 +303,7 @@ namespace Microsoft.AspNet.Mvc.Core var value = _resourceManager.GetString(name); System.Diagnostics.Debug.Assert(value != null); - + if (formatterNames != null) { for (var i = 0; i < formatterNames.Length; i++) diff --git a/src/Microsoft.AspNet.Mvc.Core/Resources.resx b/src/Microsoft.AspNet.Mvc.Core/Resources.resx index 7698b726e2..4ee4643c8b 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Resources.resx +++ b/src/Microsoft.AspNet.Mvc.Core/Resources.resx @@ -162,6 +162,9 @@ The action descriptor must be of type '{0}'. + + The value cannot be null or empty. + The '{0}' property of '{1}' must not be null. diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ControllerTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ControllerTests.cs index 25cf8e4432..0fa90f45a5 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ControllerTests.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ControllerTests.cs @@ -1,5 +1,7 @@ -using Microsoft.AspNet.Mvc.ModelBinding; +using System; +using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.Rendering; +using Microsoft.AspNet.Testing; using Xunit; namespace Microsoft.AspNet.Mvc.Core @@ -27,5 +29,59 @@ namespace Microsoft.AspNet.Mvc.Core Assert.Equal("property", controller.ViewBag.Another); Assert.Equal("property", controller.ViewData["Another"]); } + + [Fact] + public void Redirect_Temporary_SetsSameUrl() + { + // Arrange + var controller = new Controller(); + + // Act + var result = controller.Redirect("sample\\url"); + + // Assert + Assert.False(result.Permanent); + Assert.Equal("sample\\url", result.Url); + } + + [Fact] + public void Redirect_Permanent_SetsSameUrl() + { + // Arrange + var controller = new Controller(); + + // Act + var result = controller.RedirectPermanent("sample\\url"); + + // Assert + Assert.True(result.Permanent); + Assert.Equal("sample\\url", result.Url); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void Redirect_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var controller = new Controller(); + + // Act & Assert + ExceptionAssert.ThrowsArgument( + () => controller.Redirect(url: url), "url", "The value cannot be null or empty"); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void RedirectPermanent_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var controller = new Controller(); + + // Act & Assert + ExceptionAssert.ThrowsArgument( + () => controller.RedirectPermanent(url: url), "url", "The value cannot be null or empty"); + } } }