From 1e7972bd8f8c2724f6b81c7efa8775d980a5a130 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 4 Apr 2017 15:41:40 -0700 Subject: [PATCH] Add convenience methods for redirecting from a Razor Page back to itself Fuxes #5953 --- .../Page.cs | 15 ++++++ .../PageModel.cs | 15 ++++++ .../PageUrlHelperExtensions.cs | 2 +- .../RedirectToPageResult.cs | 6 --- .../RazorPagesTest.cs | 23 +++++++++ .../RedirectToPageResultTest.cs | 51 +++++++++++++++++++ .../Pages/Redirects/RedirectToSelf.cshtml | 9 ++++ 7 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 test/WebSites/RazorPagesWebSite/Pages/Redirects/RedirectToSelf.cshtml diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs index 8d39d29d36..aa00bf48c2 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs @@ -138,6 +138,21 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages return new RedirectResult(url); } + /// + /// Redirects () to the current page. + /// + /// The . + protected RedirectToPageResult RedirectToPage() + => RedirectToPage(pageName: null); + + /// + /// Redirects () to the current page with the specified . + /// + /// The parameters for a route. + /// The . + protected RedirectToPageResult RedirectToPage(object routeValues) + => RedirectToPage(pageName: null, routeValues: routeValues); + /// /// Redirects () to the specified . /// diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/PageModel.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/PageModel.cs index c5ca5d259e..2fbe594945 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/PageModel.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/PageModel.cs @@ -176,6 +176,21 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages return new RedirectResult(url); } + /// + /// Redirects () to the current page. + /// + /// The . + protected RedirectToPageResult RedirectToPage() + => RedirectToPage(pageName: null); + + /// + /// Redirects () to the current page with the specified . + /// + /// The parameters for a route. + /// The . + protected RedirectToPageResult RedirectToPage(object routeValues) + => RedirectToPage(pageName: null, routeValues: routeValues); + /// /// Redirects () to the specified . /// diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/PageUrlHelperExtensions.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/PageUrlHelperExtensions.cs index f8927dd29d..09131d5ce8 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/PageUrlHelperExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/PageUrlHelperExtensions.cs @@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Mvc /// /// Razor page specific extensions for . /// - public static class PageNameUrlHelperExtensions + public static class PageUrlHelperExtensions { /// /// Generates a URL with an absolute path for the specified . diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/RedirectToPageResult.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/RedirectToPageResult.cs index 33311dbfd2..d808d1f44b 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/RedirectToPageResult.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/RedirectToPageResult.cs @@ -130,12 +130,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages throw new ArgumentNullException(nameof(context)); } - if (string.IsNullOrEmpty(PageName)) - { - throw new InvalidOperationException( - Resources.FormatPropertyOfTypeCannotBeNull(nameof(PageName), nameof(RedirectToPageResult))); - } - var executor = context.HttpContext.RequestServices.GetRequiredService(); executor.Execute(context, this); } diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs index c7bdb62fd9..76c8012244 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs @@ -677,6 +677,29 @@ Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary`1[AspNetCore._InjectedP Assert.Equal(expected, response.Headers.Location.ToString()); } + + [Fact] + public async Task RedirectToSelfWorks() + { + // Arrange + var expected = "/Pages/Redirects/RedirectToSelf?user=37"; + var request = new HttpRequestMessage(HttpMethod.Post, "/Pages/Redirects/RedirectToSelf") + { + Content = new FormUrlEncodedContent(new KeyValuePair[] + { + new KeyValuePair("value", "37"), + }), + }; + + // Act + await AddAntiforgeryHeaders(request); + var response = await Client.SendAsync(request); + + // Assert + Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); + Assert.Equal(expected, response.Headers.Location.ToString()); + } + private async Task AddAntiforgeryHeaders(HttpRequestMessage request) { var getResponse = await Client.GetAsync(request.RequestUri); diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/RedirectToPageResultTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/RedirectToPageResultTest.cs index a284fc5ef5..da5429971d 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/RedirectToPageResultTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/RedirectToPageResultTest.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.RazorPages.Internal; @@ -123,6 +124,56 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages Assert.Equal("test-fragment", context.Fragment); } + [Fact] + public async Task RedirectToPage_WithNullPage_UsesAmbientValue() + { + // Arrange + var expected = "path/to/this-page"; + var httpContext = new Mock(); + var httpResponse = new Mock(); + httpContext.SetupGet(c => c.Response) + .Returns(httpResponse.Object); + httpContext.SetupGet(c => c.RequestServices) + .Returns(CreateServices()); + var routeData = new RouteData + { + Values = + { + ["page"] = expected, + } + }; + + var actionContext = new ActionContext( + httpContext.Object, + routeData, + new ActionDescriptor()); + + UrlRouteContext context = null; + var urlHelper = new Mock(); + urlHelper.Setup(h => h.RouteUrl(It.IsAny())) + .Callback((UrlRouteContext c) => context = c) + .Returns("some-value"); + urlHelper.SetupGet(h => h.ActionContext) + .Returns(actionContext); + var pageName = (string)null; + var result = new RedirectToPageResult(pageName) + { + UrlHelper = urlHelper.Object, + }; + + // Act + await result.ExecuteResultAsync(actionContext); + + // Assert + Assert.NotNull(context); + Assert.Collection(Assert.IsType(context.Values), + value => + { + Assert.Equal("page", value.Key); + Assert.Equal(expected, value.Value); + }); + } + private static IServiceProvider CreateServices(IUrlHelperFactory factory = null) { var services = new ServiceCollection(); diff --git a/test/WebSites/RazorPagesWebSite/Pages/Redirects/RedirectToSelf.cshtml b/test/WebSites/RazorPagesWebSite/Pages/Redirects/RedirectToSelf.cshtml new file mode 100644 index 0000000000..bc597309d0 --- /dev/null +++ b/test/WebSites/RazorPagesWebSite/Pages/Redirects/RedirectToSelf.cshtml @@ -0,0 +1,9 @@ +@page +@functions +{ + public IActionResult OnPost(int value) => RedirectToPage(new { user = value }); +} + +
+ @Html.AntiForgeryToken() +
\ No newline at end of file