[Fixes #6117] Added RedirectToPage overloads to Controller
This commit is contained in:
parent
83faaebdb6
commit
8eac7c2d6c
|
|
@ -943,6 +943,148 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>.
|
||||
/// </summary>
|
||||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
|
||||
[NonAction]
|
||||
public virtual RedirectToPageResult RedirectToPage(string pageName)
|
||||
=> RedirectToPage(pageName, routeValues: null);
|
||||
|
||||
/// <summary>
|
||||
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
|
||||
/// using the specified <paramref name="routeValues"/>.
|
||||
/// </summary>
|
||||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <param name="routeValues">The parameters for a route.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
|
||||
[NonAction]
|
||||
public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues)
|
||||
=> RedirectToPage(pageName, routeValues, fragment: null);
|
||||
|
||||
/// <summary>
|
||||
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
|
||||
/// using the specified <paramref name="fragment"/>.
|
||||
/// </summary>
|
||||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <param name="fragment">The fragment to add to the URL.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
|
||||
[NonAction]
|
||||
public virtual RedirectToPageResult RedirectToPage(string pageName, string fragment)
|
||||
=> RedirectToPage(pageName, routeValues: null, fragment: fragment);
|
||||
|
||||
/// <summary>
|
||||
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
|
||||
/// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>.
|
||||
/// </summary>
|
||||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <param name="routeValues">The parameters for a route.</param>
|
||||
/// <param name="fragment">The fragment to add to the URL.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
|
||||
[NonAction]
|
||||
public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues, string fragment)
|
||||
=> new RedirectToPageResult(pageName, routeValues, fragment);
|
||||
|
||||
/// <summary>
|
||||
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>.
|
||||
/// </summary>
|
||||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
|
||||
[NonAction]
|
||||
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName)
|
||||
=> RedirectToPagePermanent(pageName, routeValues: null);
|
||||
|
||||
/// <summary>
|
||||
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>
|
||||
/// using the specified <paramref name="routeValues"/>.
|
||||
/// </summary>
|
||||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <param name="routeValues">The parameters for a route.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
|
||||
[NonAction]
|
||||
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues)
|
||||
=> RedirectToPagePermanent(pageName, routeValues, fragment: null);
|
||||
|
||||
/// <summary>
|
||||
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>
|
||||
/// using the specified <paramref name="fragment"/>.
|
||||
/// </summary>
|
||||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <param name="fragment">The fragment to add to the URL.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
|
||||
[NonAction]
|
||||
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string fragment)
|
||||
=> RedirectToPagePermanent(pageName, routeValues: null, fragment: fragment);
|
||||
|
||||
/// <summary>
|
||||
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>
|
||||
/// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>.
|
||||
/// </summary>
|
||||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <param name="routeValues">The parameters for a route.</param>
|
||||
/// <param name="fragment">The fragment to add to the URL.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
|
||||
[NonAction]
|
||||
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues, string fragment)
|
||||
=> new RedirectToPageResult(pageName, routeValues, permanent: true, fragment: fragment);
|
||||
|
||||
/// <summary>
|
||||
/// Redirects (<see cref="StatusCodes.Status307TemporaryRedirect"/>) to the specified page with
|
||||
/// <see cref="RedirectToRouteResult.Permanent"/> set to false and <see cref="RedirectToRouteResult.PreserveMethod"/>
|
||||
/// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>.
|
||||
/// </summary>
|
||||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <param name="routeValues">The route data to use for generating the URL.</param>
|
||||
/// <param name="fragment">The fragment to add to the URL.</param>
|
||||
/// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns>
|
||||
[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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redirects (<see cref="StatusCodes.Status308PermanentRedirect"/>) to the specified route with
|
||||
/// <see cref="RedirectToRouteResult.Permanent"/> set to true and <see cref="RedirectToRouteResult.PreserveMethod"/>
|
||||
/// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>.
|
||||
/// </summary>
|
||||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <param name="routeValues">The route data to use for generating the URL.</param>
|
||||
/// <param name="fragment">The fragment to add to the URL.</param>
|
||||
/// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns>
|
||||
[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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a file with the specified <paramref name="fileContents" /> as content
|
||||
/// (<see cref="StatusCodes.Status200OK"/>) and the specified <paramref name="contentType" /> as the Content-Type.
|
||||
|
|
|
|||
|
|
@ -215,6 +215,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
services.TryAddSingleton<LocalRedirectResultExecutor>();
|
||||
services.TryAddSingleton<RedirectToActionResultExecutor>();
|
||||
services.TryAddSingleton<RedirectToRouteResultExecutor>();
|
||||
services.TryAddSingleton<RedirectToPageResultExecutor>();
|
||||
services.TryAddSingleton<ContentResultExecutor>();
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
private static readonly Action<ILogger, string[], Exception> _noActionsMatched;
|
||||
|
||||
private static readonly Action<ILogger, string, Exception> _redirectToPageResultExecuting;
|
||||
|
||||
static MvcCoreLoggerExtensions()
|
||||
{
|
||||
_actionExecuting = LoggerMessage.Define<string>(
|
||||
|
|
@ -226,6 +228,11 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
1,
|
||||
"Executing RedirectToRouteResult, redirecting to {Destination} from route {RouteName}.");
|
||||
|
||||
_redirectToPageResultExecuting = LoggerMessage.Define<string>(
|
||||
LogLevel.Information,
|
||||
1,
|
||||
"Executing RedirectToPageResult, redirecting to {Page}.");
|
||||
|
||||
_noActionsMatched = LoggerMessage.Define<string[]>(
|
||||
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<KeyValuePair<string, object>>
|
||||
{
|
||||
private readonly ActionDescriptor _action;
|
||||
|
|
@ -539,7 +549,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
for (int i = 0; i < Count; ++i)
|
||||
for (var i = 0; i < Count; ++i)
|
||||
{
|
||||
yield return this[i];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
|
||||
/// <summary>
|
||||
/// No page named '{0}' matches the supplied values.
|
||||
/// </summary>
|
||||
internal static string NoRoutesMatchedForPage
|
||||
{
|
||||
get => GetString("NoRoutesMatchedForPage");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No page named '{0}' matches the supplied values.
|
||||
/// </summary>
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="ActionResult"/> that returns a Found (302)
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
|
|
@ -26,36 +26,36 @@
|
|||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
|
|
@ -297,7 +297,7 @@
|
|||
<data name="ModelBinding_MissingBindRequiredMember" xml:space="preserve">
|
||||
<value>A value for the '{0}' property was not provided.</value>
|
||||
</data>
|
||||
<data name="ModelBinding_MissingRequestBodyRequiredMember" xml:space="preserve">
|
||||
<data name="ModelBinding_MissingRequestBodyRequiredMember" xml:space="preserve">
|
||||
<value>A non-empty request body is required.</value>
|
||||
</data>
|
||||
<data name="ValueProviderResult_NoConverterExists" xml:space="preserve">
|
||||
|
|
@ -400,4 +400,7 @@
|
|||
<data name="ComplexTypeModelBinder_NoParameterlessConstructor_ForProperty" xml:space="preserve">
|
||||
<value>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.</value>
|
||||
</data>
|
||||
<data name="NoRoutesMatchedForPage" xml:space="preserve">
|
||||
<value>No page named '{0}' matches the supplied values.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -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
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a URL with an absolute path for the specified <paramref name="pageName"/>.
|
||||
/// </summary>
|
||||
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
|
||||
/// <param name="pageName">The page name to generate the url for.</param>
|
||||
/// <returns>The generated URL.</returns>
|
||||
public static string Page(this IUrlHelper urlHelper, string pageName)
|
||||
=> Page(urlHelper, pageName, values: null);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a URL with an absolute path for the specified <paramref name="pageName"/>.
|
||||
/// </summary>
|
||||
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
|
||||
/// <param name="pageName">The page name to generate the url for.</param>
|
||||
/// <param name="values">An object that contains route values.</param>
|
||||
/// <returns>The generated URL.</returns>
|
||||
public static string Page(
|
||||
this IUrlHelper urlHelper,
|
||||
string pageName,
|
||||
object values)
|
||||
=> Page(urlHelper, pageName, values, protocol: null);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a URL with an absolute path for the specified <paramref name="pageName"/>.
|
||||
/// </summary>
|
||||
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
|
||||
/// <param name="pageName">The page name to generate the url for.</param>
|
||||
/// <param name="values">An object that contains route values.</param>
|
||||
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
|
||||
/// <returns>The generated URL.</returns>
|
||||
public static string Page(
|
||||
this IUrlHelper urlHelper,
|
||||
string pageName,
|
||||
object values,
|
||||
string protocol)
|
||||
=> Page(urlHelper, pageName, values, protocol, host: null, fragment: null);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a URL with an absolute path for the specified <paramref name="pageName"/>.
|
||||
/// </summary>
|
||||
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
|
||||
/// <param name="pageName">The page name to generate the url for.</param>
|
||||
/// <param name="values">An object that contains route values.</param>
|
||||
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
|
||||
/// <param name="host">The host name for the URL.</param>
|
||||
/// <returns>The generated URL.</returns>
|
||||
public static string Page(
|
||||
this IUrlHelper urlHelper,
|
||||
string pageName,
|
||||
object values,
|
||||
string protocol,
|
||||
string host)
|
||||
=> Page(urlHelper, pageName, values, protocol, host, fragment: null);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a URL with an absolute path for the specified <paramref name="pageName"/>.
|
||||
/// </summary>
|
||||
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
|
||||
/// <param name="pageName">The page name to generate the url for.</param>
|
||||
/// <param name="values">An object that contains route values.</param>
|
||||
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
|
||||
/// <param name="host">The host name for the URL.</param>
|
||||
/// <param name="fragment">The fragment for the URL.</param>
|
||||
/// <returns>The generated URL.</returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
|
||||
// Action executors
|
||||
services.TryAddSingleton<PageResultExecutor>();
|
||||
services.TryAddSingleton<RedirectToPageResultExecutor>();
|
||||
|
||||
services.TryAddTransient<PageSaveTempDataPropertyFilter>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
private static readonly Action<ILogger, string, double, Exception> _pageExecuted;
|
||||
private static readonly Action<ILogger, object, Exception> _exceptionFilterShortCircuit;
|
||||
private static readonly Action<ILogger, object, Exception> _pageFilterShortCircuit;
|
||||
private static readonly Action<ILogger, string, Exception> _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<string>(
|
||||
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<KeyValuePair<string, object>>
|
||||
{
|
||||
private readonly ActionDescriptor _action;
|
||||
|
|
|
|||
|
|
@ -950,7 +950,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the current page.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
|
||||
protected RedirectToPageResult RedirectToPage()
|
||||
public virtual RedirectToPageResult RedirectToPage()
|
||||
=> RedirectToPage(pageName: null);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -958,7 +958,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
/// </summary>
|
||||
/// <param name="routeValues">The parameters for a route.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
|
||||
protected RedirectToPageResult RedirectToPage(object routeValues)
|
||||
public virtual RedirectToPageResult RedirectToPage(object routeValues)
|
||||
=> RedirectToPage(pageName: null, routeValues: routeValues);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -966,7 +966,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
/// </summary>
|
||||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
|
||||
protected RedirectToPageResult RedirectToPage(string pageName)
|
||||
public virtual RedirectToPageResult RedirectToPage(string pageName)
|
||||
=> RedirectToPage(pageName, routeValues: null);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -976,7 +976,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <param name="routeValues">The parameters for a route.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
|
||||
protected RedirectToPageResult RedirectToPage(string pageName, object routeValues)
|
||||
public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues)
|
||||
=> RedirectToPage(pageName, routeValues, fragment: null);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -986,7 +986,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <param name="fragment">The fragment to add to the URL.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
|
||||
protected RedirectToPageResult RedirectToPage(string pageName, string fragment)
|
||||
public virtual RedirectToPageResult RedirectToPage(string pageName, string fragment)
|
||||
=> RedirectToPage(pageName, routeValues: null, fragment: fragment);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -997,7 +997,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
/// <param name="routeValues">The parameters for a route.</param>
|
||||
/// <param name="fragment">The fragment to add to the URL.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
|
||||
protected RedirectToPageResult RedirectToPage(string pageName, object routeValues, string fragment)
|
||||
public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues, string fragment)
|
||||
=> new RedirectToPageResult(pageName, routeValues, fragment);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1005,7 +1005,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
/// </summary>
|
||||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
|
||||
protected RedirectToPageResult RedirectToPagePermanent(string pageName)
|
||||
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName)
|
||||
=> RedirectToPagePermanent(pageName, routeValues: null);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1015,7 +1015,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <param name="routeValues">The parameters for a route.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
|
||||
protected RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues)
|
||||
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues)
|
||||
=> RedirectToPagePermanent(pageName, routeValues, fragment: null);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1025,7 +1025,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
/// <param name="pageName">The name of the page.</param>
|
||||
/// <param name="fragment">The fragment to add to the URL.</param>
|
||||
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
|
||||
protected RedirectToPageResult RedirectToPagePermanent(string pageName, string fragment)
|
||||
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string fragment)
|
||||
=> RedirectToPagePermanent(pageName, routeValues: null, fragment: fragment);
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Razor page specific extensions for <see cref="IUrlHelper"/>.
|
||||
/// </summary>
|
||||
public static class PageUrlHelperExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates a URL with an absolute path for the specified <paramref name="pageName"/>.
|
||||
/// </summary>
|
||||
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
|
||||
/// <param name="pageName">The page name to generate the url for.</param>
|
||||
/// <returns>The generated URL.</returns>
|
||||
public static string Page(this IUrlHelper urlHelper, string pageName)
|
||||
=> Page(urlHelper, pageName, values: null);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a URL with an absolute path for the specified <paramref name="pageName"/>.
|
||||
/// </summary>
|
||||
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
|
||||
/// <param name="pageName">The page name to generate the url for.</param>
|
||||
/// <param name="values">An object that contains route values.</param>
|
||||
/// <returns>The generated URL.</returns>
|
||||
public static string Page(
|
||||
this IUrlHelper urlHelper,
|
||||
string pageName,
|
||||
object values)
|
||||
=> Page(urlHelper, pageName, values, protocol: null);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a URL with an absolute path for the specified <paramref name="pageName"/>.
|
||||
/// </summary>
|
||||
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
|
||||
/// <param name="pageName">The page name to generate the url for.</param>
|
||||
/// <param name="values">An object that contains route values.</param>
|
||||
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
|
||||
/// <returns>The generated URL.</returns>
|
||||
public static string Page(
|
||||
this IUrlHelper urlHelper,
|
||||
string pageName,
|
||||
object values,
|
||||
string protocol)
|
||||
=> Page(urlHelper, pageName, values, protocol, host: null, fragment: null);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a URL with an absolute path for the specified <paramref name="pageName"/>.
|
||||
/// </summary>
|
||||
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
|
||||
/// <param name="pageName">The page name to generate the url for.</param>
|
||||
/// <param name="values">An object that contains route values.</param>
|
||||
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
|
||||
/// <param name="host">The host name for the URL.</param>
|
||||
/// <returns>The generated URL.</returns>
|
||||
public static string Page(
|
||||
this IUrlHelper urlHelper,
|
||||
string pageName,
|
||||
object values,
|
||||
string protocol,
|
||||
string host)
|
||||
=> Page(urlHelper, pageName, values, protocol, host, fragment: null);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a URL with an absolute path for the specified <paramref name="pageName"/>.
|
||||
/// </summary>
|
||||
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
|
||||
/// <param name="pageName">The page name to generate the url for.</param>
|
||||
/// <param name="values">An object that contains route values.</param>
|
||||
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
|
||||
/// <param name="host">The host name for the URL.</param>
|
||||
/// <param name="fragment">The fragment for the URL.</param>
|
||||
/// <returns>The generated URL.</returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -122,20 +122,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
internal static string FormatPathMustBeAnAppRelativePath()
|
||||
=> GetString("PathMustBeAnAppRelativePath");
|
||||
|
||||
/// <summary>
|
||||
/// No page named '{0}' matches the supplied values.
|
||||
/// </summary>
|
||||
internal static string NoRoutesMatched
|
||||
{
|
||||
get => GetString("NoRoutesMatched");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No page named '{0}' matches the supplied values.
|
||||
/// </summary>
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -141,7 +141,4 @@
|
|||
<data name="PathMustBeAnAppRelativePath" xml:space="preserve">
|
||||
<value>Path must be an application relative path that starts with a forward slash '/'.</value>
|
||||
</data>
|
||||
<data name="NoRoutesMatched" xml:space="preserve">
|
||||
<value>No page named '{0}' matches the supplied values.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -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<RedirectToPageResult>(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<KeyValuePair<string, object>> expected)
|
||||
{
|
||||
// Arrange
|
||||
var pageModel = new TestableController();
|
||||
var pageName = "CustomRouteName";
|
||||
|
||||
// Act
|
||||
var resultPermanent = pageModel.RedirectToPagePreserveMethod(pageName, routeValues);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<RedirectToPageResult>(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<KeyValuePair<string, object>> expected)
|
||||
{
|
||||
// Arrange
|
||||
var pageModel = new TestableController();
|
||||
var routeName = "CustomRouteName";
|
||||
|
||||
// Act
|
||||
var resultPermanent = pageModel.RedirectToPagePermanentPreserveMethod(routeName, routeValues);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<RedirectToPageResult>(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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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<UrlRouteContext>()))
|
||||
.Callback((UrlRouteContext context) => actual = context);
|
||||
|
||||
// Act
|
||||
urlHelper.Object.Page("TestPage");
|
||||
|
||||
// Assert
|
||||
urlHelper.Verify();
|
||||
Assert.NotNull(actual);
|
||||
Assert.Null(actual.RouteName);
|
||||
Assert.Collection(Assert.IsType<RouteValueDictionary>(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<object>
|
||||
{
|
||||
{ new { id = 10 } },
|
||||
{
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
["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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<IUrlHelper> CreateMockUrlHelper(ActionContext context = null)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
context = new ActionContext
|
||||
{
|
||||
RouteData = new RouteData(),
|
||||
};
|
||||
}
|
||||
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
urlHelper.SetupGet(h => h.ActionContext)
|
||||
.Returns(context);
|
||||
return urlHelper;
|
||||
}
|
||||
|
||||
private static HttpContext CreateHttpContext(
|
||||
IServiceProvider services,
|
||||
string appRoot)
|
||||
|
|
|
|||
|
|
@ -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<UrlRouteContext>()))
|
||||
.Callback((UrlRouteContext context) => actual = context);
|
||||
|
||||
// Act
|
||||
urlHelper.Object.Page("TestPage");
|
||||
|
||||
// Assert
|
||||
urlHelper.Verify();
|
||||
Assert.NotNull(actual);
|
||||
Assert.Null(actual.RouteName);
|
||||
Assert.Collection(Assert.IsType<RouteValueDictionary>(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<object>
|
||||
{
|
||||
{ new { id = 10 } },
|
||||
{
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
["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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<UrlRouteContext>()))
|
||||
.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<RouteValueDictionary>(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<IUrlHelper> CreateUrlHelper(ActionContext context = null)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
context = new ActionContext
|
||||
{
|
||||
RouteData = new RouteData(),
|
||||
};
|
||||
}
|
||||
|
||||
var urlHelper = new Mock<IUrlHelper>();
|
||||
urlHelper.SetupGet(h => h.ActionContext)
|
||||
.Returns(context);
|
||||
return urlHelper;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue