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