From 8eac7c2d6c69e954884fbbb97f7531548a8fc0f3 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Thu, 20 Apr 2017 17:29:13 -0700 Subject: [PATCH] [Fixes #6117] Added RedirectToPage overloads to Controller --- .../ControllerBase.cs | 142 +++++++ .../MvcCoreServiceCollectionExtensions.cs | 1 + .../Internal/MvcCoreLoggerExtensions.cs | 12 +- .../Internal/RedirectToPageResultExecutor.cs | 5 +- .../Properties/Resources.Designer.cs | 14 + .../RedirectToPageResult.cs | 4 +- .../Resources.resx | 59 +-- .../UrlHelperExtensions.cs | 108 ++++++ .../MvcRazorPagesMvcCoreBuilderExtensions.cs | 1 - .../Internal/PageLoggerExtensions.cs | 9 - .../Page.cs | 18 +- .../PageUrlHelperExtensions.cs | 121 ------ .../Properties/Resources.Designer.cs | 14 - .../Resources.resx | 3 - .../ControllerBaseTest.cs | 59 +++ .../RedirectToPageResultTest.cs | 6 +- .../Routing/UrlHelperTest.cs | 339 +++++++++++++++++ .../PageUrlHelperExtensionsTest.cs | 353 ------------------ .../Controllers/RedirectController.cs | 4 +- .../RedirectToController.cshtml | 2 +- 20 files changed, 725 insertions(+), 549 deletions(-) rename src/{Microsoft.AspNetCore.Mvc.RazorPages => Microsoft.AspNetCore.Mvc.Core}/Internal/RedirectToPageResultExecutor.cs (94%) rename src/{Microsoft.AspNetCore.Mvc.RazorPages => Microsoft.AspNetCore.Mvc.Core}/RedirectToPageResult.cs (98%) delete mode 100644 src/Microsoft.AspNetCore.Mvc.RazorPages/PageUrlHelperExtensions.cs rename test/{Microsoft.AspNetCore.Mvc.RazorPages.Test => Microsoft.AspNetCore.Mvc.Core.Test}/RedirectToPageResultTest.cs (98%) delete mode 100644 test/Microsoft.AspNetCore.Mvc.RazorPages.Test/PageUrlHelperExtensionsTest.cs diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs b/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs index a18a5297f0..49826cb116 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs @@ -943,6 +943,148 @@ namespace Microsoft.AspNetCore.Mvc }; } + /// + /// Redirects () to the specified . + /// + /// The name of the page. + /// The . + [NonAction] + public virtual RedirectToPageResult RedirectToPage(string pageName) + => RedirectToPage(pageName, routeValues: null); + + /// + /// Redirects () to the specified + /// using the specified . + /// + /// The name of the page. + /// The parameters for a route. + /// The . + [NonAction] + public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues) + => RedirectToPage(pageName, routeValues, fragment: null); + + /// + /// Redirects () to the specified + /// using the specified . + /// + /// The name of the page. + /// The fragment to add to the URL. + /// The . + [NonAction] + public virtual RedirectToPageResult RedirectToPage(string pageName, string fragment) + => RedirectToPage(pageName, routeValues: null, fragment: fragment); + + /// + /// Redirects () to the specified + /// using the specified and . + /// + /// The name of the page. + /// The parameters for a route. + /// The fragment to add to the URL. + /// The . + [NonAction] + public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues, string fragment) + => new RedirectToPageResult(pageName, routeValues, fragment); + + /// + /// Redirects () to the specified . + /// + /// The name of the page. + /// The with set. + [NonAction] + public virtual RedirectToPageResult RedirectToPagePermanent(string pageName) + => RedirectToPagePermanent(pageName, routeValues: null); + + /// + /// Redirects () to the specified + /// using the specified . + /// + /// The name of the page. + /// The parameters for a route. + /// The with set. + [NonAction] + public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues) + => RedirectToPagePermanent(pageName, routeValues, fragment: null); + + /// + /// Redirects () to the specified + /// using the specified . + /// + /// The name of the page. + /// The fragment to add to the URL. + /// The with set. + [NonAction] + public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string fragment) + => RedirectToPagePermanent(pageName, routeValues: null, fragment: fragment); + + /// + /// Redirects () to the specified + /// using the specified and . + /// + /// The name of the page. + /// The parameters for a route. + /// The fragment to add to the URL. + /// The with set. + [NonAction] + public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues, string fragment) + => new RedirectToPageResult(pageName, routeValues, permanent: true, fragment: fragment); + + /// + /// Redirects () to the specified page with + /// set to false and + /// set to true, using the specified , , and . + /// + /// The name of the page. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + [NonAction] + public virtual RedirectToPageResult RedirectToPagePreserveMethod( + string pageName, + object routeValues = null, + string fragment = null) + { + if (pageName == null) + { + throw new ArgumentNullException(nameof(pageName)); + } + + return new RedirectToPageResult( + pageName: pageName, + routeValues: routeValues, + permanent: false, + preserveMethod: true, + fragment: fragment); + } + + /// + /// Redirects () to the specified route with + /// set to true and + /// set to true, using the specified , , and . + /// + /// The name of the page. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + [NonAction] + public virtual RedirectToPageResult RedirectToPagePermanentPreserveMethod( + string pageName, + object routeValues = null, + string fragment = null) + { + if (pageName == null) + { + throw new ArgumentNullException(nameof(pageName)); + } + + return new RedirectToPageResult( + pageName: pageName, + routeValues: routeValues, + permanent: true, + preserveMethod: true, + fragment: fragment); + } + /// /// Returns a file with the specified as content /// () and the specified as the Content-Type. diff --git a/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs index 22096b039d..cb8a46daea 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs @@ -215,6 +215,7 @@ namespace Microsoft.Extensions.DependencyInjection services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); + services.TryAddSingleton(); services.TryAddSingleton(); // diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreLoggerExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreLoggerExtensions.cs index 8c725e7687..fc71bce93c 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreLoggerExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreLoggerExtensions.cs @@ -69,6 +69,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal private static readonly Action _noActionsMatched; + private static readonly Action _redirectToPageResultExecuting; + static MvcCoreLoggerExtensions() { _actionExecuting = LoggerMessage.Define( @@ -226,6 +228,11 @@ namespace Microsoft.AspNetCore.Mvc.Internal 1, "Executing RedirectToRouteResult, redirecting to {Destination} from route {RouteName}."); + _redirectToPageResultExecuting = LoggerMessage.Define( + LogLevel.Information, + 1, + "Executing RedirectToPageResult, redirecting to {Page}."); + _noActionsMatched = LoggerMessage.Define( LogLevel.Debug, 3, @@ -499,6 +506,9 @@ namespace Microsoft.AspNetCore.Mvc.Internal _redirectToRouteResultExecuting(logger, destination, routeName, null); } + public static void RedirectToPageResultExecuting(this ILogger logger, string page) + => _redirectToPageResultExecuting(logger, page, null); + private class ActionLogScope : IReadOnlyList> { private readonly ActionDescriptor _action; @@ -539,7 +549,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal public IEnumerator> GetEnumerator() { - for (int i = 0; i < Count; ++i) + for (var i = 0; i < Count; ++i) { yield return this[i]; } diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/RedirectToPageResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToPageResultExecutor.cs similarity index 94% rename from src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/RedirectToPageResultExecutor.cs rename to src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToPageResultExecutor.cs index 8ff19456af..87f3b15e04 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/RedirectToPageResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToPageResultExecutor.cs @@ -3,11 +3,12 @@ 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.RazorPages.Internal +namespace Microsoft.AspNetCore.Mvc.Internal { public class RedirectToPageResultExecutor { @@ -42,7 +43,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal if (string.IsNullOrEmpty(destinationUrl)) { - throw new InvalidOperationException(Resources.FormatNoRoutesMatched(result.PageName)); + throw new InvalidOperationException(Resources.FormatNoRoutesMatchedForPage(result.PageName)); } _logger.RedirectToPageResultExecuting(result.PageName); diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs index 044cb00dc2..a0ef1e7272 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs @@ -1270,6 +1270,20 @@ namespace Microsoft.AspNetCore.Mvc.Core internal static string FormatComplexTypeModelBinder_NoParameterlessConstructor_ForProperty(object p0, object p1, object p2) => string.Format(CultureInfo.CurrentCulture, GetString("ComplexTypeModelBinder_NoParameterlessConstructor_ForProperty"), p0, p1, p2); + /// + /// No page named '{0}' matches the supplied values. + /// + internal static string NoRoutesMatchedForPage + { + get => GetString("NoRoutesMatchedForPage"); + } + + /// + /// No page named '{0}' matches the supplied values. + /// + internal static string FormatNoRoutesMatchedForPage(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("NoRoutesMatchedForPage"), p0); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/RedirectToPageResult.cs b/src/Microsoft.AspNetCore.Mvc.Core/RedirectToPageResult.cs similarity index 98% rename from src/Microsoft.AspNetCore.Mvc.RazorPages/RedirectToPageResult.cs rename to src/Microsoft.AspNetCore.Mvc.Core/RedirectToPageResult.cs index fcb29e81b5..ae5198ae1e 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/RedirectToPageResult.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/RedirectToPageResult.cs @@ -2,12 +2,12 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.AspNetCore.Mvc.RazorPages.Internal; +using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; -namespace Microsoft.AspNetCore.Mvc.RazorPages +namespace Microsoft.AspNetCore.Mvc { /// /// An that returns a Found (302) diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx b/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx index 1ba794f649..5853677f91 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx +++ b/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx @@ -1,17 +1,17 @@  - @@ -297,7 +297,7 @@ A value for the '{0}' property was not provided. - + A non-empty request body is required. @@ -400,4 +400,7 @@ Could not create an instance of type '{0}'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, set the '{1}' property to a non-null value in the '{2}' constructor. + + No page named '{0}' matches the supplied values. + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.Core/UrlHelperExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Core/UrlHelperExtensions.cs index 87f42790dc..b6de84b716 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/UrlHelperExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/UrlHelperExtensions.cs @@ -3,6 +3,7 @@ using System; using Microsoft.AspNetCore.Mvc.Routing; +using Microsoft.AspNetCore.Routing; namespace Microsoft.AspNetCore.Mvc { @@ -332,5 +333,112 @@ namespace Microsoft.AspNetCore.Mvc Fragment = fragment }); } + + /// + /// Generates a URL with an absolute path for the specified . + /// + /// The . + /// The page name to generate the url for. + /// The generated URL. + public static string Page(this IUrlHelper urlHelper, string pageName) + => Page(urlHelper, pageName, values: null); + + /// + /// Generates a URL with an absolute path for the specified . + /// + /// The . + /// The page name to generate the url for. + /// An object that contains route values. + /// The generated URL. + public static string Page( + this IUrlHelper urlHelper, + string pageName, + object values) + => Page(urlHelper, pageName, values, protocol: null); + + /// + /// Generates a URL with an absolute path for the specified . + /// + /// The . + /// The page name to generate the url for. + /// An object that contains route values. + /// The protocol for the URL, such as "http" or "https". + /// The generated URL. + public static string Page( + this IUrlHelper urlHelper, + string pageName, + object values, + string protocol) + => Page(urlHelper, pageName, values, protocol, host: null, fragment: null); + + /// + /// Generates a URL with an absolute path for the specified . + /// + /// The . + /// The page name to generate the url for. + /// An object that contains route values. + /// The protocol for the URL, such as "http" or "https". + /// The host name for the URL. + /// The generated URL. + public static string Page( + this IUrlHelper urlHelper, + string pageName, + object values, + string protocol, + string host) + => Page(urlHelper, pageName, values, protocol, host, fragment: null); + + /// + /// Generates a URL with an absolute path for the specified . + /// + /// The . + /// The page name to generate the url for. + /// An object that contains route values. + /// The protocol for the URL, such as "http" or "https". + /// The host name for the URL. + /// The fragment for the URL. + /// The generated URL. + public static string Page( + this IUrlHelper urlHelper, + string pageName, + object values, + string protocol, + string host, + string fragment) + { + if (urlHelper == null) + { + throw new ArgumentNullException(nameof(urlHelper)); + } + + var routeValues = new RouteValueDictionary(values); + var ambientValues = urlHelper.ActionContext.RouteData.Values; + if (pageName == null) + { + if (!routeValues.ContainsKey("page") && + ambientValues.TryGetValue("page", out var value)) + { + routeValues["page"] = value; + } + } + else + { + routeValues["page"] = pageName; + } + + if (!routeValues.ContainsKey("formaction") && + ambientValues.TryGetValue("formaction", out var formaction)) + { + // Clear out formaction unless it's explicitly specified in the routeValues. + routeValues["formaction"] = null; + } + + return urlHelper.RouteUrl( + routeName: null, + values: routeValues, + protocol: protocol, + host: host, + fragment: fragment); + } } } diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/DependencyInjection/MvcRazorPagesMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/DependencyInjection/MvcRazorPagesMvcCoreBuilderExtensions.cs index 9dcd2a91cf..bdd060d539 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/DependencyInjection/MvcRazorPagesMvcCoreBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/DependencyInjection/MvcRazorPagesMvcCoreBuilderExtensions.cs @@ -102,7 +102,6 @@ namespace Microsoft.Extensions.DependencyInjection // Action executors services.TryAddSingleton(); - services.TryAddSingleton(); services.TryAddTransient(); } diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageLoggerExtensions.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageLoggerExtensions.cs index ad8589227b..516f86f719 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageLoggerExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageLoggerExtensions.cs @@ -18,7 +18,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal private static readonly Action _pageExecuted; private static readonly Action _exceptionFilterShortCircuit; private static readonly Action _pageFilterShortCircuit; - private static readonly Action _redirectToPageResultExecuting; static PageLoggerExtensions() { @@ -41,11 +40,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal LogLevel.Debug, 3, "Request was short circuited at page filter '{PageFilter}'."); - - _redirectToPageResultExecuting = LoggerMessage.Define( - LogLevel.Information, - 5, - "Executing RedirectToPageResult, redirecting to {Page}."); } public static IDisposable PageScope(this ILogger logger, ActionDescriptor actionDescriptor) @@ -87,9 +81,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal _pageFilterShortCircuit(logger, filter, null); } - public static void RedirectToPageResultExecuting(this ILogger logger, string page) - => _redirectToPageResultExecuting(logger, page, null); - private class PageLogScope : IReadOnlyList> { private readonly ActionDescriptor _action; diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs index f6c38e2600..a906de2141 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs @@ -950,7 +950,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// Redirects () to the current page. /// /// The . - protected RedirectToPageResult RedirectToPage() + public virtual RedirectToPageResult RedirectToPage() => RedirectToPage(pageName: null); /// @@ -958,7 +958,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// /// The parameters for a route. /// The . - protected RedirectToPageResult RedirectToPage(object routeValues) + public virtual RedirectToPageResult RedirectToPage(object routeValues) => RedirectToPage(pageName: null, routeValues: routeValues); /// @@ -966,7 +966,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// /// The name of the page. /// The . - protected RedirectToPageResult RedirectToPage(string pageName) + public virtual RedirectToPageResult RedirectToPage(string pageName) => RedirectToPage(pageName, routeValues: null); /// @@ -976,7 +976,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The name of the page. /// The parameters for a route. /// The . - protected RedirectToPageResult RedirectToPage(string pageName, object routeValues) + public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues) => RedirectToPage(pageName, routeValues, fragment: null); /// @@ -986,7 +986,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The name of the page. /// The fragment to add to the URL. /// The . - protected RedirectToPageResult RedirectToPage(string pageName, string fragment) + public virtual RedirectToPageResult RedirectToPage(string pageName, string fragment) => RedirectToPage(pageName, routeValues: null, fragment: fragment); /// @@ -997,7 +997,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The parameters for a route. /// The fragment to add to the URL. /// The . - protected RedirectToPageResult RedirectToPage(string pageName, object routeValues, string fragment) + public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues, string fragment) => new RedirectToPageResult(pageName, routeValues, fragment); /// @@ -1005,7 +1005,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// /// The name of the page. /// The with set. - protected RedirectToPageResult RedirectToPagePermanent(string pageName) + public virtual RedirectToPageResult RedirectToPagePermanent(string pageName) => RedirectToPagePermanent(pageName, routeValues: null); /// @@ -1015,7 +1015,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The name of the page. /// The parameters for a route. /// The with set. - protected RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues) + public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues) => RedirectToPagePermanent(pageName, routeValues, fragment: null); /// @@ -1025,7 +1025,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The name of the page. /// The fragment to add to the URL. /// The with set. - protected RedirectToPageResult RedirectToPagePermanent(string pageName, string fragment) + public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string fragment) => RedirectToPagePermanent(pageName, routeValues: null, fragment: fragment); /// diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/PageUrlHelperExtensions.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/PageUrlHelperExtensions.cs deleted file mode 100644 index c786bf5a11..0000000000 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/PageUrlHelperExtensions.cs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Routing; - -namespace Microsoft.AspNetCore.Mvc -{ - /// - /// Razor page specific extensions for . - /// - public static class PageUrlHelperExtensions - { - /// - /// Generates a URL with an absolute path for the specified . - /// - /// The . - /// The page name to generate the url for. - /// The generated URL. - public static string Page(this IUrlHelper urlHelper, string pageName) - => Page(urlHelper, pageName, values: null); - - /// - /// Generates a URL with an absolute path for the specified . - /// - /// The . - /// The page name to generate the url for. - /// An object that contains route values. - /// The generated URL. - public static string Page( - this IUrlHelper urlHelper, - string pageName, - object values) - => Page(urlHelper, pageName, values, protocol: null); - - /// - /// Generates a URL with an absolute path for the specified . - /// - /// The . - /// The page name to generate the url for. - /// An object that contains route values. - /// The protocol for the URL, such as "http" or "https". - /// The generated URL. - public static string Page( - this IUrlHelper urlHelper, - string pageName, - object values, - string protocol) - => Page(urlHelper, pageName, values, protocol, host: null, fragment: null); - - /// - /// Generates a URL with an absolute path for the specified . - /// - /// The . - /// The page name to generate the url for. - /// An object that contains route values. - /// The protocol for the URL, such as "http" or "https". - /// The host name for the URL. - /// The generated URL. - public static string Page( - this IUrlHelper urlHelper, - string pageName, - object values, - string protocol, - string host) - => Page(urlHelper, pageName, values, protocol, host, fragment: null); - - /// - /// Generates a URL with an absolute path for the specified . - /// - /// The . - /// The page name to generate the url for. - /// An object that contains route values. - /// The protocol for the URL, such as "http" or "https". - /// The host name for the URL. - /// The fragment for the URL. - /// The generated URL. - public static string Page( - this IUrlHelper urlHelper, - string pageName, - object values, - string protocol, - string host, - string fragment) - { - if (urlHelper == null) - { - throw new ArgumentNullException(nameof(urlHelper)); - } - - var routeValues = new RouteValueDictionary(values); - var ambientValues = urlHelper.ActionContext.RouteData.Values; - if (pageName == null) - { - if (!routeValues.ContainsKey("page") && - ambientValues.TryGetValue("page", out var value)) - { - routeValues["page"] = value; - } - } - else - { - routeValues["page"] = pageName; - } - - if (!routeValues.ContainsKey("formaction") && - ambientValues.TryGetValue("formaction", out var formaction)) - { - // Clear out formaction unless it's explicitly specified in the routeValues. - routeValues["formaction"] = null; - } - - return urlHelper.RouteUrl( - routeName: null, - values: routeValues, - protocol: protocol, - host: host, - fragment: fragment); - } - } -} diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Properties/Resources.Designer.cs index 433b9d9b37..cd6c6a8aa1 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Properties/Resources.Designer.cs @@ -122,20 +122,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages internal static string FormatPathMustBeAnAppRelativePath() => GetString("PathMustBeAnAppRelativePath"); - /// - /// No page named '{0}' matches the supplied values. - /// - internal static string NoRoutesMatched - { - get => GetString("NoRoutesMatched"); - } - - /// - /// No page named '{0}' matches the supplied values. - /// - internal static string FormatNoRoutesMatched(object p0) - => string.Format(CultureInfo.CurrentCulture, GetString("NoRoutesMatched"), p0); - private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Resources.resx b/src/Microsoft.AspNetCore.Mvc.RazorPages/Resources.resx index d20e8d0844..2e8f00040c 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Resources.resx +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Resources.resx @@ -141,7 +141,4 @@ Path must be an application relative path that starts with a forward slash '/'. - - No page named '{0}' matches the supplied values. - \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs index 7c0fb679c7..1244681fb5 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs @@ -986,6 +986,65 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test Assert.Equal(expected, resultPermanent.RouteValues); } + [Fact] + public void RedirectToPagePreserveMethod_WithParameterUrl_SetsRedirectResultPreserveMethod() + { + // Arrange + var pageModel = new TestableController(); + var url = "/test/url"; + + // Act + var result = pageModel.RedirectToPagePreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Same(url, result.PageName); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToPagePreserveMethod_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestableController(); + var pageName = "CustomRouteName"; + + // Act + var resultPermanent = pageModel.RedirectToPagePreserveMethod(pageName, routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.False(resultPermanent.Permanent); + Assert.Same(pageName, resultPermanent.PageName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToPagePermanentPreserveMethod_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestableController(); + var routeName = "CustomRouteName"; + + // Act + var resultPermanent = pageModel.RedirectToPagePermanentPreserveMethod(routeName, routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Same(routeName, resultPermanent.PageName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + [Theory] [MemberData(nameof(RedirectTestData))] public void RedirectToRoutePermanentPreserveMethod_WithParameterRouteNameAndRouteValues_SetsResultProperties( diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/RedirectToPageResultTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectToPageResultTest.cs similarity index 98% rename from test/Microsoft.AspNetCore.Mvc.RazorPages.Test/RedirectToPageResultTest.cs rename to test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectToPageResultTest.cs index ffb90722f7..fe7b3b7672 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/RedirectToPageResultTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/RedirectToPageResultTest.cs @@ -4,10 +4,10 @@ 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; +using Microsoft.AspNetCore.Mvc.Internal; +using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Testing; @@ -17,7 +17,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; -namespace Microsoft.AspNetCore.Mvc.RazorPages +namespace Microsoft.AspNetCore.Mvc { public class RedirectToPageResultTest { diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Routing/UrlHelperTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Routing/UrlHelperTest.cs index 63deb0fb37..0b6147bd5e 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Routing/UrlHelperTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Routing/UrlHelperTest.cs @@ -1031,6 +1031,345 @@ namespace Microsoft.AspNetCore.Mvc.Routing Assert.Same(urlHelper, actionContext.HttpContext.Items[typeof(IUrlHelper)] as IUrlHelper); } + [Fact] + public void Page_WithName_Works() + { + // Arrange + UrlRouteContext actual = null; + var routeData = new RouteData + { + Values = + { + { "page", "ambient-page" }, + } + }; + var actionContext = new ActionContext + { + RouteData = routeData, + }; + var urlHelper = CreateMockUrlHelper(actionContext); + urlHelper.Setup(h => h.RouteUrl(It.IsAny())) + .Callback((UrlRouteContext context) => actual = context); + + // Act + urlHelper.Object.Page("TestPage"); + + // Assert + urlHelper.Verify(); + Assert.NotNull(actual); + Assert.Null(actual.RouteName); + Assert.Collection(Assert.IsType(actual.Values), + value => + { + Assert.Equal("page", value.Key); + Assert.Equal("TestPage", value.Value); + }); + Assert.Null(actual.Host); + Assert.Null(actual.Protocol); + Assert.Null(actual.Fragment); + } + + public static TheoryData Page_WithNameAndRouteValues_WorksData + { + get => new TheoryData + { + { new { id = 10 } }, + { + new Dictionary + { + ["id"] = 10, + } + }, + { + new RouteValueDictionary + { + ["id"] = 10, + } + }, + }; + } + + [Theory] + [MemberData(nameof(Page_WithNameAndRouteValues_WorksData))] + public void Page_WithNameAndRouteValues_Works(object values) + { + // Arrange + UrlRouteContext actual = null; + var urlHelper = CreateMockUrlHelper(); + urlHelper.Setup(h => h.RouteUrl(It.IsAny())) + .Callback((UrlRouteContext context) => actual = context); + + // Act + urlHelper.Object.Page("TestPage", values); + + // Assert + urlHelper.Verify(); + Assert.NotNull(actual); + Assert.Null(actual.RouteName); + Assert.Collection(Assert.IsType(actual.Values), + value => + { + Assert.Equal("id", value.Key); + Assert.Equal(10, value.Value); + }, + value => + { + Assert.Equal("page", value.Key); + Assert.Equal("TestPage", value.Value); + }); + Assert.Null(actual.Host); + Assert.Null(actual.Protocol); + Assert.Null(actual.Fragment); + } + + [Fact] + public void Page_WithNameRouteValuesAndProtocol_Works() + { + // Arrange + UrlRouteContext actual = null; + var urlHelper = CreateMockUrlHelper(); + urlHelper.Setup(h => h.RouteUrl(It.IsAny())) + .Callback((UrlRouteContext context) => actual = context); + + // Act + urlHelper.Object.Page("TestPage", new { id = 13 }, "https"); + + // Assert + urlHelper.Verify(); + Assert.NotNull(actual); + Assert.Null(actual.RouteName); + Assert.Collection(Assert.IsType(actual.Values), + value => + { + Assert.Equal("id", value.Key); + Assert.Equal(13, value.Value); + }, + value => + { + Assert.Equal("page", value.Key); + Assert.Equal("TestPage", value.Value); + }); + Assert.Equal("https", actual.Protocol); + Assert.Null(actual.Host); + Assert.Null(actual.Fragment); + } + + [Fact] + public void Page_WithNameRouteValuesProtocolAndHost_Works() + { + // Arrange + UrlRouteContext actual = null; + var urlHelper = CreateMockUrlHelper(); + urlHelper.Setup(h => h.RouteUrl(It.IsAny())) + .Callback((UrlRouteContext context) => actual = context); + + // Act + urlHelper.Object.Page("TestPage", new { id = 13 }, "https", "mytesthost"); + + // Assert + urlHelper.Verify(); + Assert.NotNull(actual); + Assert.Null(actual.RouteName); + Assert.Collection(Assert.IsType(actual.Values), + value => + { + Assert.Equal("id", value.Key); + Assert.Equal(13, value.Value); + }, + value => + { + Assert.Equal("page", value.Key); + Assert.Equal("TestPage", value.Value); + }); + Assert.Equal("https", actual.Protocol); + Assert.Equal("mytesthost", actual.Host); + Assert.Null(actual.Fragment); + } + + [Fact] + public void Page_WithNameRouteValuesProtocolHostAndFragment_Works() + { + // Arrange + UrlRouteContext actual = null; + var urlHelper = CreateMockUrlHelper(); + urlHelper.Setup(h => h.RouteUrl(It.IsAny())) + .Callback((UrlRouteContext context) => actual = context); + + // Act + urlHelper.Object.Page("TestPage", new { id = 13 }, "https", "mytesthost", "#toc"); + + // Assert + urlHelper.Verify(); + Assert.NotNull(actual); + Assert.Null(actual.RouteName); + Assert.Collection(Assert.IsType(actual.Values), + value => + { + Assert.Equal("id", value.Key); + Assert.Equal(13, value.Value); + }, + value => + { + Assert.Equal("page", value.Key); + Assert.Equal("TestPage", value.Value); + }); + Assert.Equal("https", actual.Protocol); + Assert.Equal("mytesthost", actual.Host); + Assert.Equal("#toc", actual.Fragment); + } + + [Fact] + public void Page_UsesAmbientRouteValue_WhenPageIsNull() + { + // Arrange + UrlRouteContext actual = null; + var routeData = new RouteData + { + Values = + { + { "page", "ambient-page" }, + } + }; + var actionContext = new ActionContext + { + RouteData = routeData, + }; + + var urlHelper = CreateMockUrlHelper(actionContext); + urlHelper.Setup(h => h.RouteUrl(It.IsAny())) + .Callback((UrlRouteContext context) => actual = context); + + // Act + string page = null; + urlHelper.Object.Page(page, new { id = 13 }, "https", "mytesthost", "#toc"); + + // Assert + urlHelper.Verify(); + Assert.NotNull(actual); + Assert.Null(actual.RouteName); + Assert.Collection(Assert.IsType(actual.Values), + value => + { + Assert.Equal("id", value.Key); + Assert.Equal(13, value.Value); + }, + value => + { + Assert.Equal("page", value.Key); + Assert.Equal("ambient-page", value.Value); + }); + Assert.Equal("https", actual.Protocol); + Assert.Equal("mytesthost", actual.Host); + Assert.Equal("#toc", actual.Fragment); + } + + [Fact] + public void Page_SetsFormActionToNull_IfValueIsNotSpecifiedInRouteValues() + { + // Arrange + UrlRouteContext actual = null; + var routeData = new RouteData + { + Values = + { + { "page", "ambient-page" }, + { "formaction", "ambient-formaction" }, + } + }; + var actionContext = new ActionContext + { + RouteData = routeData, + }; + + var urlHelper = CreateMockUrlHelper(actionContext); + urlHelper.Setup(h => h.RouteUrl(It.IsAny())) + .Callback((UrlRouteContext context) => actual = context); + + // Act + string page = null; + urlHelper.Object.Page(page, new { id = 13 }, "https", "mytesthost", "#toc"); + + // Assert + urlHelper.Verify(); + Assert.NotNull(actual); + Assert.Null(actual.RouteName); + Assert.Collection(Assert.IsType(actual.Values), + value => + { + Assert.Equal("id", value.Key); + Assert.Equal(13, value.Value); + }, + value => + { + Assert.Equal("page", value.Key); + Assert.Equal("ambient-page", value.Value); + }, + value => + { + Assert.Equal("formaction", value.Key); + Assert.Null(value.Value); + }); + } + + [Fact] + public void Page_UsesExplicitlySpecifiedFormActionValue() + { + // Arrange + UrlRouteContext actual = null; + var routeData = new RouteData + { + Values = + { + { "page", "ambient-page" }, + { "formaction", "ambient-formaction" }, + } + }; + var actionContext = new ActionContext + { + RouteData = routeData, + }; + + var urlHelper = CreateMockUrlHelper(actionContext); + urlHelper.Setup(h => h.RouteUrl(It.IsAny())) + .Callback((UrlRouteContext context) => actual = context); + + // Act + string page = null; + urlHelper.Object.Page(page, new { formaction = "exact-formaction" }, "https", "mytesthost", "#toc"); + + // Assert + urlHelper.Verify(); + Assert.NotNull(actual); + Assert.Null(actual.RouteName); + Assert.Collection(Assert.IsType(actual.Values), + value => + { + Assert.Equal("formaction", value.Key); + Assert.Equal("exact-formaction", value.Value); + }, + value => + { + Assert.Equal("page", value.Key); + Assert.Equal("ambient-page", value.Value); + }); + } + + private static Mock CreateMockUrlHelper(ActionContext context = null) + { + if (context == null) + { + context = new ActionContext + { + RouteData = new RouteData(), + }; + } + + var urlHelper = new Mock(); + urlHelper.SetupGet(h => h.ActionContext) + .Returns(context); + return urlHelper; + } + private static HttpContext CreateHttpContext( IServiceProvider services, string appRoot) diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/PageUrlHelperExtensionsTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/PageUrlHelperExtensionsTest.cs deleted file mode 100644 index 5fd67db646..0000000000 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/PageUrlHelperExtensionsTest.cs +++ /dev/null @@ -1,353 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using Microsoft.AspNetCore.Mvc.Routing; -using Microsoft.AspNetCore.Routing; -using Moq; -using Xunit; - -namespace Microsoft.AspNetCore.Mvc.RazorPages -{ - public class PageUrlHelperExtensionsTest - { - [Fact] - public void Page_WithName_Works() - { - // Arrange - UrlRouteContext actual = null; - var routeData = new RouteData - { - Values = - { - { "page", "ambient-page" }, - } - }; - var actionContext = new ActionContext - { - RouteData = routeData, - }; - var urlHelper = CreateUrlHelper(actionContext); - urlHelper.Setup(h => h.RouteUrl(It.IsAny())) - .Callback((UrlRouteContext context) => actual = context); - - // Act - urlHelper.Object.Page("TestPage"); - - // Assert - urlHelper.Verify(); - Assert.NotNull(actual); - Assert.Null(actual.RouteName); - Assert.Collection(Assert.IsType(actual.Values), - value => - { - Assert.Equal("page", value.Key); - Assert.Equal("TestPage", value.Value); - }); - Assert.Null(actual.Host); - Assert.Null(actual.Protocol); - Assert.Null(actual.Fragment); - } - - public static TheoryData Page_WithNameAndRouteValues_WorksData - { - get => new TheoryData - { - { new { id = 10 } }, - { - new Dictionary - { - ["id"] = 10, - } - }, - { - new RouteValueDictionary - { - ["id"] = 10, - } - }, - }; - } - - [Theory] - [MemberData(nameof(Page_WithNameAndRouteValues_WorksData))] - public void Page_WithNameAndRouteValues_Works(object values) - { - // Arrange - UrlRouteContext actual = null; - var urlHelper = CreateUrlHelper(); - urlHelper.Setup(h => h.RouteUrl(It.IsAny())) - .Callback((UrlRouteContext context) => actual = context); - - // Act - urlHelper.Object.Page("TestPage", values); - - // Assert - urlHelper.Verify(); - Assert.NotNull(actual); - Assert.Null(actual.RouteName); - Assert.Collection(Assert.IsType(actual.Values), - value => - { - Assert.Equal("id", value.Key); - Assert.Equal(10, value.Value); - }, - value => - { - Assert.Equal("page", value.Key); - Assert.Equal("TestPage", value.Value); - }); - Assert.Null(actual.Host); - Assert.Null(actual.Protocol); - Assert.Null(actual.Fragment); - } - - [Fact] - public void Page_WithNameRouteValuesAndProtocol_Works() - { - // Arrange - UrlRouteContext actual = null; - var urlHelper = CreateUrlHelper(); - urlHelper.Setup(h => h.RouteUrl(It.IsAny())) - .Callback((UrlRouteContext context) => actual = context); - - // Act - urlHelper.Object.Page("TestPage", new { id = 13 }, "https"); - - // Assert - urlHelper.Verify(); - Assert.NotNull(actual); - Assert.Null(actual.RouteName); - Assert.Collection(Assert.IsType(actual.Values), - value => - { - Assert.Equal("id", value.Key); - Assert.Equal(13, value.Value); - }, - value => - { - Assert.Equal("page", value.Key); - Assert.Equal("TestPage", value.Value); - }); - Assert.Equal("https", actual.Protocol); - Assert.Null(actual.Host); - Assert.Null(actual.Fragment); - } - - [Fact] - public void Page_WithNameRouteValuesProtocolAndHost_Works() - { - // Arrange - UrlRouteContext actual = null; - var urlHelper = CreateUrlHelper(); - urlHelper.Setup(h => h.RouteUrl(It.IsAny())) - .Callback((UrlRouteContext context) => actual = context); - - // Act - urlHelper.Object.Page("TestPage", new { id = 13 }, "https", "mytesthost"); - - // Assert - urlHelper.Verify(); - Assert.NotNull(actual); - Assert.Null(actual.RouteName); - Assert.Collection(Assert.IsType(actual.Values), - value => - { - Assert.Equal("id", value.Key); - Assert.Equal(13, value.Value); - }, - value => - { - Assert.Equal("page", value.Key); - Assert.Equal("TestPage", value.Value); - }); - Assert.Equal("https", actual.Protocol); - Assert.Equal("mytesthost", actual.Host); - Assert.Null(actual.Fragment); - } - - [Fact] - public void Page_WithNameRouteValuesProtocolHostAndFragment_Works() - { - // Arrange - UrlRouteContext actual = null; - var urlHelper = CreateUrlHelper(); - urlHelper.Setup(h => h.RouteUrl(It.IsAny())) - .Callback((UrlRouteContext context) => actual = context); - - // Act - urlHelper.Object.Page("TestPage", new { id = 13 }, "https", "mytesthost", "#toc"); - - // Assert - urlHelper.Verify(); - Assert.NotNull(actual); - Assert.Null(actual.RouteName); - Assert.Collection(Assert.IsType(actual.Values), - value => - { - Assert.Equal("id", value.Key); - Assert.Equal(13, value.Value); - }, - value => - { - Assert.Equal("page", value.Key); - Assert.Equal("TestPage", value.Value); - }); - Assert.Equal("https", actual.Protocol); - Assert.Equal("mytesthost", actual.Host); - Assert.Equal("#toc", actual.Fragment); - } - - [Fact] - public void Page_UsesAmbientRouteValue_WhenPageIsNull() - { - // Arrange - UrlRouteContext actual = null; - var routeData = new RouteData - { - Values = - { - { "page", "ambient-page" }, - } - }; - var actionContext = new ActionContext - { - RouteData = routeData, - }; - - var urlHelper = CreateUrlHelper(actionContext); - urlHelper.Setup(h => h.RouteUrl(It.IsAny())) - .Callback((UrlRouteContext context) => actual = context); - - // Act - string page = null; - urlHelper.Object.Page(page, new { id = 13 }, "https", "mytesthost", "#toc"); - - // Assert - urlHelper.Verify(); - Assert.NotNull(actual); - Assert.Null(actual.RouteName); - Assert.Collection(Assert.IsType(actual.Values), - value => - { - Assert.Equal("id", value.Key); - Assert.Equal(13, value.Value); - }, - value => - { - Assert.Equal("page", value.Key); - Assert.Equal("ambient-page", value.Value); - }); - Assert.Equal("https", actual.Protocol); - Assert.Equal("mytesthost", actual.Host); - Assert.Equal("#toc", actual.Fragment); - } - - [Fact] - public void Page_SetsFormActionToNull_IfValueIsNotSpecifiedInRouteValues() - { - // Arrange - UrlRouteContext actual = null; - var routeData = new RouteData - { - Values = - { - { "page", "ambient-page" }, - { "formaction", "ambient-formaction" }, - } - }; - var actionContext = new ActionContext - { - RouteData = routeData, - }; - - var urlHelper = CreateUrlHelper(actionContext); - urlHelper.Setup(h => h.RouteUrl(It.IsAny())) - .Callback((UrlRouteContext context) => actual = context); - - // Act - string page = null; - urlHelper.Object.Page(page, new { id = 13 }, "https", "mytesthost", "#toc"); - - // Assert - urlHelper.Verify(); - Assert.NotNull(actual); - Assert.Null(actual.RouteName); - Assert.Collection(Assert.IsType(actual.Values), - value => - { - Assert.Equal("id", value.Key); - Assert.Equal(13, value.Value); - }, - value => - { - Assert.Equal("page", value.Key); - Assert.Equal("ambient-page", value.Value); - }, - value => - { - Assert.Equal("formaction", value.Key); - Assert.Null(value.Value); - }); - } - - [Fact] - public void Page_UsesExplicitlySpecifiedFormActionValue() - { - // Arrange - UrlRouteContext actual = null; - var routeData = new RouteData - { - Values = - { - { "page", "ambient-page" }, - { "formaction", "ambient-formaction" }, - } - }; - var actionContext = new ActionContext - { - RouteData = routeData, - }; - - var urlHelper = CreateUrlHelper(actionContext); - urlHelper.Setup(h => h.RouteUrl(It.IsAny())) - .Callback((UrlRouteContext context) => actual = context); - - // Act - string page = null; - urlHelper.Object.Page(page, new { formaction = "exact-formaction" }, "https", "mytesthost", "#toc"); - - // Assert - urlHelper.Verify(); - Assert.NotNull(actual); - Assert.Null(actual.RouteName); - Assert.Collection(Assert.IsType(actual.Values), - value => - { - Assert.Equal("formaction", value.Key); - Assert.Equal("exact-formaction", value.Value); - }, - value => - { - Assert.Equal("page", value.Key); - Assert.Equal("ambient-page", value.Value); - }); - } - - private static Mock CreateUrlHelper(ActionContext context = null) - { - if (context == null) - { - context = new ActionContext - { - RouteData = new RouteData(), - }; - } - - var urlHelper = new Mock(); - urlHelper.SetupGet(h => h.ActionContext) - .Returns(context); - return urlHelper; - } - } -} diff --git a/test/WebSites/RazorPagesWebSite/Controllers/RedirectController.cs b/test/WebSites/RazorPagesWebSite/Controllers/RedirectController.cs index 073a63a85b..ea9a070809 100644 --- a/test/WebSites/RazorPagesWebSite/Controllers/RedirectController.cs +++ b/test/WebSites/RazorPagesWebSite/Controllers/RedirectController.cs @@ -8,9 +8,9 @@ namespace RazorPagesWebSite public class RedirectController : Controller { [HttpGet("/RedirectToPage")] - public IActionResult RedirectToPage() + public IActionResult RedirectToPageAction() { - return RedirectToRoute(new { page = "/RedirectToController", param = 17 }); + return RedirectToPage("/RedirectToController", new { param = 17 }); } } } diff --git a/test/WebSites/RazorPagesWebSite/RedirectToController.cshtml b/test/WebSites/RazorPagesWebSite/RedirectToController.cshtml index cd4f5dcb15..fbb709631a 100644 --- a/test/WebSites/RazorPagesWebSite/RedirectToController.cshtml +++ b/test/WebSites/RazorPagesWebSite/RedirectToController.cshtml @@ -3,6 +3,6 @@ @functions { public IActionResult OnGet() { - return new RedirectToRouteResult(new { controller = "Redirect", action = "RedirectToPage", param = 92 }); + return new RedirectToRouteResult(new { controller = "Redirect", action = "RedirectToPageAction", param = 92 }); } } \ No newline at end of file