From 1a8ac88da76be830a1505a7cc3a41b58a4ea7c3b Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Mon, 10 Apr 2017 17:31:59 -0700 Subject: [PATCH] Add PreserveMethod (#6075) Addresses #5609 --- .../ControllerBase.cs | 186 ++++++- .../Internal/LocalRedirectResultExecutor.cs | 14 +- .../Internal/RedirectResultExecutor.cs | 14 +- .../RedirectToActionResultExecutor.cs | 14 +- .../Internal/RedirectToRouteResultExecutor.cs | 14 +- .../LocalRedirectResult.cs | 21 +- .../RedirectResult.cs | 43 ++ .../RedirectToActionResult.cs | 50 +- .../RedirectToRouteResult.cs | 46 +- .../ControllerBaseTest.cs | 522 +++++++++++++++++- .../LocalRedirectResultTest.cs | 21 +- .../RedirectResultTest.cs | 21 +- .../RedirectToActionResultTest.cs | 28 + .../RedirectToRouteResultTest.cs | 25 + 14 files changed, 1001 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs b/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs index 0939847439..af3d9331c9 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs @@ -328,7 +328,7 @@ namespace Microsoft.AspNetCore.Mvc /// The created object for the response. [NonAction] public virtual NoContentResult NoContent() - { + { return new NoContentResult(); } @@ -387,6 +387,42 @@ namespace Microsoft.AspNetCore.Mvc return new RedirectResult(url, permanent: true); } + /// + /// Creates a object with set to false + /// and set to true () + /// using the specified . + /// + /// The URL to redirect to. + /// The created for the response. + [NonAction] + public virtual RedirectResult RedirectPreserveMethod(string url) + { + if (string.IsNullOrEmpty(url)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(url)); + } + + return new RedirectResult(url: url, permanent: false, preserveMethod: true); + } + + /// + /// Creates a object with set to true + /// and set to true () + /// using the specified . + /// + /// The URL to redirect to. + /// The created for the response. + [NonAction] + public virtual RedirectResult RedirectPermanentPreserveMethod(string url) + { + if (string.IsNullOrEmpty(url)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(url)); + } + + return new RedirectResult(url: url, permanent: true, preserveMethod: true); + } + /// /// Creates a object that redirects /// () to the specified local . @@ -421,6 +457,42 @@ namespace Microsoft.AspNetCore.Mvc return new LocalRedirectResult(localUrl, permanent: true); } + /// + /// Creates a object with set to + /// false and set to true + /// () using the specified . + /// + /// The local URL to redirect to. + /// The created for the response. + [NonAction] + public virtual LocalRedirectResult LocalRedirectPreserveMethod(string localUrl) + { + if (string.IsNullOrEmpty(localUrl)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(localUrl)); + } + + return new LocalRedirectResult(localUrl: localUrl, permanent: false, preserveMethod: true); + } + + /// + /// Creates a object with set to + /// true and set to true + /// () using the specified . + /// + /// The local URL to redirect to. + /// The created for the response. + [NonAction] + public virtual LocalRedirectResult LocalRedirectPermanentPreserveMethod(string localUrl) + { + if (string.IsNullOrEmpty(localUrl)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(localUrl)); + } + + return new LocalRedirectResult(localUrl: localUrl, permanent: true, preserveMethod: true); + } + /// /// Redirects () to the specified action using the . /// @@ -514,6 +586,36 @@ namespace Microsoft.AspNetCore.Mvc }; } + /// + /// Redirects () to the specified action with + /// set to false and + /// set to true, using the specified , , + /// , and . + /// + /// The name of the action. + /// The name of the controller. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + [NonAction] + public virtual RedirectToActionResult RedirectToActionPreserveMethod( + string actionName = null, + string controllerName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToActionResult( + actionName: actionName, + controllerName: controllerName, + routeValues: routeValues, + permanent: false, + preserveMethod: true, + fragment: fragment) + { + UrlHelper = Url, + }; + } + /// /// Redirects () to the specified action with /// set to true using the specified . @@ -618,6 +720,36 @@ namespace Microsoft.AspNetCore.Mvc }; } + /// + /// Redirects () to the specified action with + /// set to true and + /// set to true, using the specified , , + /// , and . + /// + /// The name of the action. + /// The name of the controller. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + [NonAction] + public virtual RedirectToActionResult RedirectToActionPermanentPreserveMethod( + string actionName = null, + string controllerName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToActionResult( + actionName: actionName, + controllerName: controllerName, + routeValues: routeValues, + permanent: true, + preserveMethod: true, + fragment: fragment) + { + UrlHelper = Url, + }; + } + /// /// Redirects () to the specified route using the specified . /// @@ -686,6 +818,32 @@ namespace Microsoft.AspNetCore.Mvc }; } + /// + /// Redirects () to the specified route with + /// set to false and + /// set to true, using the specified , , and . + /// + /// The name of the route. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + [NonAction] + public virtual RedirectToRouteResult RedirectToRoutePreserveMethod( + string routeName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToRouteResult( + routeName: routeName, + routeValues: routeValues, + permanent: false, + preserveMethod: true, + fragment: fragment) + { + UrlHelper = Url, + }; + } + /// /// Redirects () to the specified route with /// set to true using the specified . @@ -759,6 +917,32 @@ namespace Microsoft.AspNetCore.Mvc }; } + /// + /// Redirects () to the specified route with + /// set to true and + /// set to true, using the specified , , and . + /// + /// The name of the route. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + [NonAction] + public virtual RedirectToRouteResult RedirectToRoutePermanentPreserveMethod( + string routeName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToRouteResult( + routeName: routeName, + routeValues: routeValues, + permanent: true, + preserveMethod: true, + fragment: fragment) + { + UrlHelper = Url, + }; + } + /// /// Returns a file with the specified as content /// () and the specified as the Content-Type. diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/LocalRedirectResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/LocalRedirectResultExecutor.cs index ec98081004..94a0978293 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/LocalRedirectResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/LocalRedirectResultExecutor.cs @@ -2,9 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Core; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.Extensions.Logging; +using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.Mvc.Internal { @@ -42,7 +44,17 @@ namespace Microsoft.AspNetCore.Mvc.Internal destinationUrl = urlHelper.Content(result.Url); _logger.LocalRedirectResultExecuting(destinationUrl); - context.HttpContext.Response.Redirect(destinationUrl, result.Permanent); + + if (result.PreserveMethod) + { + context.HttpContext.Response.StatusCode = result.Permanent ? + StatusCodes.Status308PermanentRedirect : StatusCodes.Status307TemporaryRedirect; + context.HttpContext.Response.Headers[HeaderNames.Location] = destinationUrl; + } + else + { + context.HttpContext.Response.Redirect(destinationUrl, result.Permanent); + } } } } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectResultExecutor.cs index 8251f191da..4e8d47d45c 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectResultExecutor.cs @@ -2,8 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.Extensions.Logging; +using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.Mvc.Internal { @@ -40,7 +42,17 @@ namespace Microsoft.AspNetCore.Mvc.Internal } _logger.RedirectResultExecuting(destinationUrl); - context.HttpContext.Response.Redirect(destinationUrl, result.Permanent); + + if (result.PreserveMethod) + { + context.HttpContext.Response.StatusCode = result.Permanent ? + StatusCodes.Status308PermanentRedirect : StatusCodes.Status307TemporaryRedirect; + context.HttpContext.Response.Headers[HeaderNames.Location] = destinationUrl; + } + else + { + context.HttpContext.Response.Redirect(destinationUrl, result.Permanent); + } } } } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToActionResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToActionResultExecutor.cs index 119d54d4cd..d6ed3e3aef 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToActionResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToActionResultExecutor.cs @@ -2,9 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Core; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.Extensions.Logging; +using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.Mvc.Internal { @@ -46,7 +48,17 @@ namespace Microsoft.AspNetCore.Mvc.Internal } _logger.RedirectToActionResultExecuting(destinationUrl); - context.HttpContext.Response.Redirect(destinationUrl, result.Permanent); + + if (result.PreserveMethod) + { + context.HttpContext.Response.StatusCode = result.Permanent ? + StatusCodes.Status308PermanentRedirect : StatusCodes.Status307TemporaryRedirect; + context.HttpContext.Response.Headers[HeaderNames.Location] = destinationUrl; + } + else + { + context.HttpContext.Response.Redirect(destinationUrl, result.Permanent); + } } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToRouteResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToRouteResultExecutor.cs index 758a639a95..5b16b3683b 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToRouteResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToRouteResultExecutor.cs @@ -2,9 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Core; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.Extensions.Logging; +using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.Mvc.Internal { @@ -45,7 +47,17 @@ namespace Microsoft.AspNetCore.Mvc.Internal } _logger.RedirectToRouteResultExecuting(destinationUrl, result.RouteName); - context.HttpContext.Response.Redirect(destinationUrl, result.Permanent); + + if (result.PreserveMethod) + { + context.HttpContext.Response.StatusCode = result.Permanent ? + StatusCodes.Status308PermanentRedirect : StatusCodes.Status307TemporaryRedirect; + context.HttpContext.Response.Headers[HeaderNames.Location] = destinationUrl; + } + else + { + context.HttpContext.Response.Redirect(destinationUrl, result.Permanent); + } } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.Core/LocalRedirectResult.cs b/src/Microsoft.AspNetCore.Mvc.Core/LocalRedirectResult.cs index 626a1b3b30..a06b3e8f99 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/LocalRedirectResult.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/LocalRedirectResult.cs @@ -9,7 +9,8 @@ using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Mvc { /// - /// An that returns a redirect to the supplied local URL. + /// An that returns a Found (302), Moved Permanently (301), Temporary Redirect (307), + /// or Permanent Redirect (308) response with a Location header to the supplied local URL. /// public class LocalRedirectResult : ActionResult { @@ -32,6 +33,18 @@ namespace Microsoft.AspNetCore.Mvc /// The local URL to redirect to. /// Specifies whether the redirect should be permanent (301) or temporary (302). public LocalRedirectResult(string localUrl, bool permanent) + : this(localUrl, permanent, preserveMethod: false) + { + } + + /// + /// Initializes a new instance of the class with the values + /// provided. + /// + /// The local URL to redirect to. + /// Specifies whether the redirect should be permanent (301) or temporary (302). + /// If set to true, make the temporary redirect (307) or permanent redirect (308) preserve the intial request's method. + public LocalRedirectResult(string localUrl, bool permanent, bool preserveMethod) { if (string.IsNullOrEmpty(localUrl)) { @@ -39,6 +52,7 @@ namespace Microsoft.AspNetCore.Mvc } Permanent = permanent; + PreserveMethod = preserveMethod; Url = localUrl; } @@ -47,6 +61,11 @@ namespace Microsoft.AspNetCore.Mvc /// public bool Permanent { get; set; } + /// + /// Gets or sets an indication that the redirect preserves the initial request method. + /// + public bool PreserveMethod { get; set; } + /// /// Gets or sets the local URL to redirect to. /// diff --git a/src/Microsoft.AspNetCore.Mvc.Core/RedirectResult.cs b/src/Microsoft.AspNetCore.Mvc.Core/RedirectResult.cs index 39e2b98db9..0341fa801e 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/RedirectResult.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/RedirectResult.cs @@ -9,10 +9,19 @@ using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Mvc { + /// + /// An that returns a Found (302), Moved Permanently (301), Temporary Redirect (307), + /// or Permanent Redirect (308) response with a Location header to the supplied URL. + /// public class RedirectResult : ActionResult, IKeepTempDataResult { private string _url; + /// + /// Initializes a new instance of the class with the values + /// provided. + /// + /// The local URL to redirect to. public RedirectResult(string url) : this(url, permanent: false) { @@ -22,7 +31,25 @@ namespace Microsoft.AspNetCore.Mvc } } + /// + /// Initializes a new instance of the class with the values + /// provided. + /// + /// The URL to redirect to. + /// Specifies whether the redirect should be permanent (301) or temporary (302). public RedirectResult(string url, bool permanent) + : this(url, permanent, preserveMethod: false) + { + } + + /// + /// Initializes a new instance of the class with the values + /// provided. + /// + /// The URL to redirect to. + /// Specifies whether the redirect should be permanent (301) or temporary (302). + /// If set to true, make the temporary redirect (307) or permanent redirect (308) preserve the intial request method. + public RedirectResult(string url, bool permanent, bool preserveMethod) { if (url == null) { @@ -35,11 +62,23 @@ namespace Microsoft.AspNetCore.Mvc } Permanent = permanent; + PreserveMethod = preserveMethod; Url = url; } + /// + /// Gets or sets the value that specifies that the redirect should be permanent if true or temporary if false. + /// public bool Permanent { get; set; } + /// + /// Gets or sets an indication that the redirect preserves the initial request method. + /// + public bool PreserveMethod { get; set; } + + /// + /// Gets or sets the URL to redirect to. + /// public string Url { get @@ -57,8 +96,12 @@ namespace Microsoft.AspNetCore.Mvc } } + /// + /// Gets or sets the for this result. + /// public IUrlHelper UrlHelper { get; set; } + /// public override void ExecuteResult(ActionContext context) { if (context == null) diff --git a/src/Microsoft.AspNetCore.Mvc.Core/RedirectToActionResult.cs b/src/Microsoft.AspNetCore.Mvc.Core/RedirectToActionResult.cs index ae83e5601e..d763cc9a48 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/RedirectToActionResult.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/RedirectToActionResult.cs @@ -10,8 +10,8 @@ using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Mvc { /// - /// An that returns a Found (302) - /// or Moved Permanently (301) response with a Location header. + /// An that returns a Found (302), Moved Permanently (301), Temporary Redirect (307), + /// or Permanent Redirect (308) response with a Location header. /// Targets a controller action. /// public class RedirectToActionResult : ActionResult, IKeepTempDataResult @@ -65,6 +65,25 @@ namespace Microsoft.AspNetCore.Mvc { } + /// + /// Initializes a new instance of the with the values + /// provided. + /// + /// The name of the action to use for generating the URL. + /// The name of the controller to use for generating the URL. + /// The route data to use for generating the URL. + /// If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302). + /// If set to true, make the temporary redirect (307) or permanent redirect (308) preserve the intial request method. + public RedirectToActionResult( + string actionName, + string controllerName, + object routeValues, + bool permanent, + bool preserveMethod) + : this(actionName, controllerName, routeValues, permanent, preserveMethod, fragment: null) + { + } + /// /// Initializes a new instance of the with the values /// provided. @@ -80,11 +99,33 @@ namespace Microsoft.AspNetCore.Mvc object routeValues, bool permanent, string fragment) + : this(actionName, controllerName, routeValues, permanent, preserveMethod: false, fragment: fragment) + { + } + + /// + /// Initializes a new instance of the with the values + /// provided. + /// + /// The name of the action to use for generating the URL. + /// The name of the controller to use for generating the URL. + /// The route data to use for generating the URL. + /// If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302). + /// If set to true, make the temporary redirect (307) and permanent redirect (308) preserve the intial request method. + /// The fragment to add to the URL. + public RedirectToActionResult( + string actionName, + string controllerName, + object routeValues, + bool permanent, + bool preserveMethod, + string fragment) { ActionName = actionName; ControllerName = controllerName; RouteValues = routeValues == null ? null : new RouteValueDictionary(routeValues); Permanent = permanent; + PreserveMethod = preserveMethod; Fragment = fragment; } @@ -113,6 +154,11 @@ namespace Microsoft.AspNetCore.Mvc /// public bool Permanent { get; set; } + /// + /// Gets or sets an indication that the redirect preserves the initial request method. + /// + public bool PreserveMethod { get; set; } + /// /// Gets or sets the fragment to add to the URL. /// diff --git a/src/Microsoft.AspNetCore.Mvc.Core/RedirectToRouteResult.cs b/src/Microsoft.AspNetCore.Mvc.Core/RedirectToRouteResult.cs index 3241b13731..b68add42d4 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/RedirectToRouteResult.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/RedirectToRouteResult.cs @@ -10,8 +10,8 @@ using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Mvc { /// - /// An that returns a Found (302) - /// or Moved Permanently (301) response with a Location header. + /// An that returns a Found (302), Moved Permanently (301), Temporary Redirect (307), + /// or Permanent Redirect (308) response with a Location header. /// Targets a registered route. /// public class RedirectToRouteResult : ActionResult, IKeepTempDataResult @@ -54,6 +54,23 @@ namespace Microsoft.AspNetCore.Mvc { } + /// + /// Initializes a new instance of the with the values + /// provided. + /// + /// The name of the route. + /// The parameters for the route. + /// If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302). + /// If set to true, make the temporary redirect (307) or permanent redirect (308) preserve the intial request method. + public RedirectToRouteResult( + string routeName, + object routeValues, + bool permanent, + bool preserveMethod) + : this(routeName, routeValues, permanent, preserveMethod, fragment: null) + { + } + /// /// Initializes a new instance of the with the values /// provided. @@ -82,9 +99,29 @@ namespace Microsoft.AspNetCore.Mvc object routeValues, bool permanent, string fragment) + : this(routeName, routeValues, permanent, preserveMethod: false, fragment: fragment) + { + } + + /// + /// Initializes a new instance of the with the values + /// provided. + /// + /// The name of the route. + /// The parameters for the route. + /// If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302). + /// If set to true, make the temporary redirect (307) or permanent redirect (308) preserve the intial request method. + /// The fragment to add to the URL. + public RedirectToRouteResult( + string routeName, + object routeValues, + bool permanent, + bool preserveMethod, + string fragment) { RouteName = routeName; RouteValues = routeValues == null ? null : new RouteValueDictionary(routeValues); + PreserveMethod = preserveMethod; Permanent = permanent; Fragment = fragment; } @@ -109,6 +146,11 @@ namespace Microsoft.AspNetCore.Mvc /// public bool Permanent { get; set; } + /// + /// Gets or sets an indication that the redirect preserves the initial request method. + /// + public bool PreserveMethod { get; set; } + /// /// Gets or sets the fragment to add to the URL. /// diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs index f256c43bd5..7c0fb679c7 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs @@ -14,7 +14,6 @@ using Microsoft.AspNetCore.Mvc.DataAnnotations.Internal; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.AspNetCore.Mvc.ModelBinding.Test; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using Microsoft.AspNetCore.Mvc.TestCommon; using Microsoft.AspNetCore.Routing; @@ -52,6 +51,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(result); + Assert.False(result.PreserveMethod); Assert.False(result.Permanent); Assert.Same(url, result.Url); } @@ -68,6 +68,41 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void RedirectPermanent_WithParameterUrl_SetsRedirectResultPreserveMethodAndSameUrl() + { + // Arrange + var controller = new TestableController(); + var url = "/test/url"; + + // Act + var result = controller.RedirectPreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void RedirectPermanent_WithParameterUrl_SetsRedirectResultPermanentPreserveMethodAndSameUrl() + { + // Arrange + var controller = new TestableController(); + var url = "/test/url"; + + // Act + var result = controller.RedirectPermanentPreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); Assert.True(result.Permanent); Assert.Same(url, result.Url); } @@ -85,6 +120,19 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test () => controller.Redirect(url: url), "url"); } + [Theory] + [InlineData(null)] + [InlineData("")] + public void RedirectPreserveMethod_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var controller = new TestableController(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => controller.RedirectPreserveMethod(url: url), "url"); + } + [Fact] public void LocalRedirect_WithParameterUrl_SetsLocalRedirectResultWithSameUrl() { @@ -97,6 +145,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(result); + Assert.False(result.PreserveMethod); Assert.False(result.Permanent); Assert.Same(url, result.Url); } @@ -113,6 +162,41 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void LocalRedirectPermanent_WithParameterUrl_SetsLocalRedirectResultPreserveMethodWithSameUrl() + { + // Arrange + var controller = new TestableController(); + var url = "/test/url"; + + // Act + var result = controller.LocalRedirectPreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void LocalRedirectPermanent_WithParameterUrl_SetsLocalRedirectResultPermanentPreservesMethodWithSameUrl() + { + // Arrange + var controller = new TestableController(); + var url = "/test/url"; + + // Act + var result = controller.LocalRedirectPermanentPreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); Assert.True(result.Permanent); Assert.Same(url, result.Url); } @@ -130,6 +214,32 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test () => controller.LocalRedirect(localUrl: url), "localUrl"); } + [Theory] + [InlineData(null)] + [InlineData("")] + public void LocalRedirectPreserveMethod_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var controller = new TestableController(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => controller.LocalRedirectPreserveMethod(localUrl: url), "localUrl"); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void LocalRedirectPermanentPreserveMethod_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var controller = new TestableController(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => controller.LocalRedirectPermanentPreserveMethod(localUrl: url), "localUrl"); + } + [Theory] [InlineData(null)] [InlineData("")] @@ -143,6 +253,19 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test () => controller.RedirectPermanent(url: url), "url"); } + [Theory] + [InlineData(null)] + [InlineData("")] + public void RedirectPermanentPreserveMethod_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var controller = new TestableController(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => controller.RedirectPermanentPreserveMethod(url: url), "url"); + } + [Fact] public void RedirectToAction_WithParameterActionName_SetsResultActionName() { @@ -154,6 +277,23 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + } + + [Fact] + public void RedirectToActionPreserveMethod_WithParameterActionName_SetsResultActionName() + { + // Arrange + var controller = new TestableController(); + + // Act + var resultTemporary = controller.RedirectToActionPreserveMethod(actionName: "SampleAction"); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); Assert.False(resultTemporary.Permanent); Assert.Equal("SampleAction", resultTemporary.ActionName); } @@ -169,6 +309,23 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + } + + [Fact] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionName_SetsResultActionNameAndPermanent() + { + // Arrange + var controller = new TestableController(); + + // Act + var resultPermanent = controller.RedirectToActionPermanentPreserveMethod(actionName: "SampleAction"); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); Assert.True(resultPermanent.Permanent); Assert.Equal("SampleAction", resultPermanent.ActionName); } @@ -187,6 +344,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); Assert.False(resultTemporary.Permanent); Assert.Equal("SampleAction", resultTemporary.ActionName); Assert.Equal(controllerName, resultTemporary.ControllerName); @@ -196,8 +354,27 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test [InlineData("")] [InlineData(null)] [InlineData("SampleController")] - public void RedirectToActionPermanent_WithParameterActionAndControllerName_SetsEqualNames( - string controllerName) + public void RedirectToActionPreserveMethod_WithParameterActionAndControllerName_SetsEqualNames(string controllerName) + { + // Arrange + var controller = new TestableController(); + + // Act + var resultTemporary = controller.RedirectToActionPreserveMethod(actionName: "SampleAction", controllerName: controllerName); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + Assert.Equal(controllerName, resultTemporary.ControllerName); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + [InlineData("SampleController")] + public void RedirectToActionPermanent_WithParameterActionAndControllerName_SetsEqualNames(string controllerName) { // Arrange var controller = new TestableController(); @@ -207,6 +384,27 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + Assert.Equal(controllerName, resultPermanent.ControllerName); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + [InlineData("SampleController")] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionAndControllerName_SetsEqualNames(string controllerName) + { + // Arrange + var controller = new TestableController(); + + // Act + var resultPermanent = controller.RedirectToActionPermanentPreserveMethod(actionName: "SampleAction", controllerName: controllerName); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); Assert.True(resultPermanent.Permanent); Assert.Equal("SampleAction", resultPermanent.ActionName); Assert.Equal(controllerName, resultPermanent.ControllerName); @@ -226,6 +424,31 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + Assert.Equal("SampleController", resultTemporary.ControllerName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPreserveMethod_WithParameterActionControllerRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var controller = new TestableController(); + + // Act + var resultTemporary = controller.RedirectToActionPreserveMethod( + actionName: "SampleAction", + controllerName: "SampleController", + routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); Assert.False(resultTemporary.Permanent); Assert.Equal("SampleAction", resultTemporary.ActionName); Assert.Equal("SampleController", resultTemporary.ControllerName); @@ -249,6 +472,31 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + Assert.Equal("SampleController", resultPermanent.ControllerName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionControllerRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var controller = new TestableController(); + + // Act + var resultPermanent = controller.RedirectToActionPermanentPreserveMethod( + actionName: "SampleAction", + controllerName: "SampleController", + routeValues: routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); Assert.True(resultPermanent.Permanent); Assert.Equal("SampleAction", resultPermanent.ActionName); Assert.Equal("SampleController", resultPermanent.ControllerName); @@ -269,6 +517,27 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Null(resultTemporary.ActionName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPreserveMethod_WithParameterActionAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var controller = new TestableController(); + + // Act + var resultTemporary = controller.RedirectToActionPreserveMethod(actionName: null, routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); Assert.False(resultTemporary.Permanent); Assert.Null(resultTemporary.ActionName); Assert.Equal(expected, resultTemporary.RouteValues); @@ -291,6 +560,32 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Equal(expectedAction, result.ActionName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedController, result.ControllerName); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPreserveMethod_WithParameterActionAndControllerAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var controller = new TestableController(); + var expectedAction = "Action"; + var expectedController = "Home"; + var expectedFragment = "test"; + + // Act + var result = controller.RedirectToActionPreserveMethod("Action", "Home", routeValues, "test"); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); Assert.False(result.Permanent); Assert.Equal(expectedAction, result.ActionName); Assert.Equal(expectedRouteValues, result.RouteValues); @@ -312,6 +607,27 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Null(resultPermanent.ActionName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var controller = new TestableController(); + + // Act + var resultPermanent = controller.RedirectToActionPermanentPreserveMethod(actionName: null, routeValues: routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); Assert.True(resultPermanent.Permanent); Assert.Null(resultPermanent.ActionName); Assert.Equal(expected, resultPermanent.RouteValues); @@ -330,10 +646,40 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test var expectedFragment = "test"; // Act - var result = controller.RedirectToActionPermanent("Action", "Home", routeValues, "test"); + var result = controller.RedirectToActionPermanent("Action", "Home", routeValues, fragment: "test"); // Assert Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Equal(expectedAction, result.ActionName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedController, result.ControllerName); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionAndControllerAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var controller = new TestableController(); + var expectedAction = "Action"; + var expectedController = "Home"; + var expectedFragment = "test"; + + // Act + var result = controller.RedirectToActionPermanentPreserveMethod( + actionName: "Action", + controllerName: "Home", + routeValues: routeValues, + fragment: "test"); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); Assert.True(result.Permanent); Assert.Equal(expectedAction, result.ActionName); Assert.Equal(expectedRouteValues, result.RouteValues); @@ -355,6 +701,26 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePreserveMethod_WithParameterRouteValues_SetsResultEqualRouteValues( + object routeValues, + IEnumerable> expected) + { + // Arrange + var controller = new TestableController(); + + // Act + var resultTemporary = controller.RedirectToRoutePreserveMethod(routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); Assert.False(resultTemporary.Permanent); Assert.Equal(expected, resultTemporary.RouteValues); } @@ -375,6 +741,30 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Equal(expectedRoute, result.RouteName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePreserveMethod_WithParameterRouteNameAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var controller = new TestableController(); + var expectedRoute = "TestRoute"; + var expectedFragment = "test"; + + // Act + var result = controller.RedirectToRoutePreserveMethod(routeName: "TestRoute", routeValues: routeValues, fragment: "test"); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); Assert.False(result.Permanent); Assert.Equal(expectedRoute, result.RouteName); Assert.Equal(expectedRouteValues, result.RouteValues); @@ -395,6 +785,26 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanentPreserveMethod_WithParameterRouteValues_SetsResultEqualRouteValuesAndPermanent( + object routeValues, + IEnumerable> expected) + { + // Arrange + var controller = new TestableController(); + + // Act + var resultPermanent = controller.RedirectToRoutePermanentPreserveMethod(routeValues: routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); Assert.True(resultPermanent.Permanent); Assert.Equal(expected, resultPermanent.RouteValues); } @@ -415,6 +825,30 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Equal(expectedRoute, result.RouteName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanentPreserveMethod_WithParameterRouteNameAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var controller = new TestableController(); + var expectedRoute = "TestRoute"; + var expectedFragment = "test"; + + // Act + var result = controller.RedirectToRoutePermanentPreserveMethod(routeName: "TestRoute", routeValues: routeValues, fragment: "test"); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); Assert.True(result.Permanent); Assert.Equal(expectedRoute, result.RouteName); Assert.Equal(expectedRouteValues, result.RouteValues); @@ -433,6 +867,24 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Same(routeName, resultTemporary.RouteName); + } + + [Fact] + public void RedirectToRoutePreserveMethod_WithParameterRouteName_SetsResultSameRouteName() + { + // Arrange + var controller = new TestableController(); + var routeName = "CustomRouteName"; + + // Act; + var resultTemporary = controller.RedirectToRoutePreserveMethod(routeName: routeName); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); Assert.False(resultTemporary.Permanent); Assert.Same(routeName, resultTemporary.RouteName); } @@ -449,6 +901,24 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Same(routeName, resultPermanent.RouteName); + } + + [Fact] + public void RedirectToRoutePermanentPreserveMethod_WithParameterRouteName_SetsResultSameRouteNameAndPermanent() + { + // Arrange + var controller = new TestableController(); + var routeName = "CustomRouteName"; + + // Act + var resultPermanent = controller.RedirectToRoutePermanentPreserveMethod(routeName: routeName); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); Assert.True(resultPermanent.Permanent); Assert.Same(routeName, resultPermanent.RouteName); } @@ -468,6 +938,28 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Same(routeName, resultTemporary.RouteName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePreserveMethod_WithParameterRouteNameAndRouteValues_SetsResultSameRouteNameAndRouteValues( + object routeValues, + IEnumerable> expected) + { + // Arrange + var controller = new TestableController(); + var routeName = "CustomRouteName"; + + // Act + var resultTemporary = controller.RedirectToRoutePreserveMethod(routeName: routeName, routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); Assert.False(resultTemporary.Permanent); Assert.Same(routeName, resultTemporary.RouteName); Assert.Equal(expected, resultTemporary.RouteValues); @@ -488,6 +980,28 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test // Assert Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Same(routeName, resultPermanent.RouteName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanentPreserveMethod_WithParameterRouteNameAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var controller = new TestableController(); + var routeName = "CustomRouteName"; + + // Act + var resultPermanent = controller.RedirectToRoutePermanentPreserveMethod(routeName: routeName, routeValues: routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); Assert.True(resultPermanent.Permanent); Assert.Same(routeName, resultPermanent.RouteName); Assert.Equal(expected, resultPermanent.RouteValues); diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/LocalRedirectResultTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/LocalRedirectResultTest.cs index 0800763755..0409d15052 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/LocalRedirectResultTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/LocalRedirectResultTest.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc public class LocalRedirectResultTest { [Fact] - public void Constructor_WithParameterUrl_SetsResultUrlAndNotPermanent() + public void Constructor_WithParameterUrl_SetsResultUrlAndNotPermanentOrPreserveMethod() { // Arrange var url = "/test/url"; @@ -27,12 +27,13 @@ namespace Microsoft.AspNetCore.Mvc var result = new LocalRedirectResult(url); // Assert + Assert.False(result.PreserveMethod); Assert.False(result.Permanent); Assert.Same(url, result.Url); } [Fact] - public void Constructor_WithParameterUrlAndPermanent_SetsResultUrlAndPermanent() + public void Constructor_WithParameterUrlAndPermanent_SetsResultUrlAndPermanentNotPreserveMethod() { // Arrange var url = "/test/url"; @@ -41,6 +42,22 @@ namespace Microsoft.AspNetCore.Mvc var result = new LocalRedirectResult(url, permanent: true); // Assert + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void Constructor_WithParameterUrlAndPermanent_SetsResultUrlPermanentAndPreserveMethod() + { + // Arrange + var url = "/test/url"; + + // Act + var result = new LocalRedirectResult(url, permanent: true, preserveMethod: true); + + // Assert + Assert.True(result.PreserveMethod); Assert.True(result.Permanent); Assert.Same(url, result.Url); } diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectResultTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectResultTest.cs index e6685f9bbf..be398a6235 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectResultTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectResultTest.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc public class RedirectResultTest { [Fact] - public void RedirectResult_Constructor_WithParameterUrl_SetsResultUrlAndNotPermanent() + public void RedirectResult_Constructor_WithParameterUrl_SetsResultUrlAndNotPermanentOrPreserveMethod() { // Arrange var url = "/test/url"; @@ -27,12 +27,13 @@ namespace Microsoft.AspNetCore.Mvc var result = new RedirectResult(url); // Assert + Assert.False(result.PreserveMethod); Assert.False(result.Permanent); Assert.Same(url, result.Url); } [Fact] - public void RedirectResult_Constructor_WithParameterUrlAndPermanent_SetsResultUrlAndPermanent() + public void RedirectResult_Constructor_WithParameterUrlAndPermanent_SetsResultUrlAndPermanentNotPreserveMethod() { // Arrange var url = "/test/url"; @@ -41,6 +42,22 @@ namespace Microsoft.AspNetCore.Mvc var result = new RedirectResult(url, permanent: true); // Assert + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void RedirectResult_Constructor_WithParameterUrlPermanentAndPreservesMethod_SetsResultUrlPermanentAndPreservesMethod() + { + // Arrange + var url = "/test/url"; + + // Act + var result = new RedirectResult(url, permanent: true, preserveMethod: true); + + // Assert + Assert.True(result.PreserveMethod); Assert.True(result.Permanent); Assert.Same(url, result.Url); } diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectToActionResultTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectToActionResultTest.cs index 8cbaa40669..ee9045ffe1 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectToActionResultTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectToActionResultTest.cs @@ -111,6 +111,34 @@ namespace Microsoft.AspNetCore.Mvc Assert.Equal(expectedUrl, httpContext.Response.Headers["Location"]); } + [Fact] + public async Task RedirectToAction_Execute_WithFragment_PassesCorrectValuesToRedirect_WithPreserveMethod() + { + // Arrange + var expectedUrl = "/Home/SampleAction#test"; + var expectedStatusCode = StatusCodes.Status307TemporaryRedirect; + + var httpContext = new DefaultHttpContext + { + RequestServices = CreateServices().BuildServiceProvider(), + }; + + var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); + + var urlHelper = GetMockUrlHelper(expectedUrl); + var result = new RedirectToActionResult("SampleAction", "Home", null, false, true, "test") + { + UrlHelper = urlHelper, + }; + + // Act + await result.ExecuteResultAsync(actionContext); + + // Assert + Assert.Equal(expectedStatusCode, httpContext.Response.StatusCode); + Assert.Equal(expectedUrl, httpContext.Response.Headers["Location"]); + } + private static IUrlHelper GetMockUrlHelper(string returnValue) { var urlHelper = new Mock(); diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectToRouteResultTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectToRouteResultTest.cs index b91585d30c..0b03b3efe6 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectToRouteResultTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectToRouteResultTest.cs @@ -141,6 +141,31 @@ namespace Microsoft.AspNetCore.Mvc Assert.Equal(expectedUrl, httpContext.Response.Headers["Location"]); } + [Fact] + public async Task ExecuteResultAsync_WithFragment_PassesCorrectValuesToRedirect_WithPreserveMethod() + { + // Arrange + var expectedUrl = "/SampleAction#test"; + var expectedStatusCode = StatusCodes.Status308PermanentRedirect; + + var httpContext = GetHttpContext(); + + var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); + + var urlHelper = GetMockUrlHelper(expectedUrl); + var result = new RedirectToRouteResult("Sample", null, true, true, "test") + { + UrlHelper = urlHelper, + }; + + // Act + await result.ExecuteResultAsync(actionContext); + + // Assert + Assert.Equal(expectedStatusCode, httpContext.Response.StatusCode); + Assert.Equal(expectedUrl, httpContext.Response.Headers["Location"]); + } + private static HttpContext GetHttpContext(IUrlHelperFactory factory = null) { var services = CreateServices(factory);