Add support for page handler to URL generating APIs.

This commit is contained in:
Pranav K 2017-04-24 15:02:07 -07:00
parent ef0333ac6a
commit 649ee4d28d
25 changed files with 507 additions and 125 deletions

View File

@ -961,30 +961,54 @@ namespace Microsoft.AspNetCore.Mvc
/// <returns>The <see cref="RedirectToPageResult"/>.</returns> /// <returns>The <see cref="RedirectToPageResult"/>.</returns>
[NonAction] [NonAction]
public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues) public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues)
=> RedirectToPage(pageName, routeValues, fragment: null); => RedirectToPage(pageName, pageHandler: null, routeValues: routeValues, fragment: null);
/// <summary>
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="pageHandler"/>.
/// </summary>
/// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
[NonAction]
public virtual RedirectToPageResult RedirectToPage(string pageName, string pageHandler)
=> RedirectToPage(pageName, pageHandler, routeValues: null);
/// <summary>
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>.
/// </summary>
/// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for a route.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
[NonAction]
public virtual RedirectToPageResult RedirectToPage(string pageName, string pageHandler, object routeValues)
=> RedirectToPage(pageName, pageHandler, routeValues);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="fragment"/>. /// using the specified <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns> /// <returns>The <see cref="RedirectToPageResult"/>.</returns>
[NonAction] [NonAction]
public virtual RedirectToPageResult RedirectToPage(string pageName, string fragment) public virtual RedirectToPageResult RedirectToPage(string pageName, string pageHandler, string fragment)
=> RedirectToPage(pageName, routeValues: null, fragment: fragment); => RedirectToPage(pageName, pageHandler, routeValues: null, fragment: fragment);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>. /// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for a route.</param> /// <param name="routeValues">The parameters for a route.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns> /// <returns>The <see cref="RedirectToPageResult"/>.</returns>
[NonAction] [NonAction]
public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues, string fragment) public virtual RedirectToPageResult RedirectToPage(string pageName, string pageHandler, object routeValues, string fragment)
=> new RedirectToPageResult(pageName, routeValues, fragment); => new RedirectToPageResult(pageName, pageHandler, routeValues, fragment);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>. /// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>.
@ -1004,30 +1028,49 @@ namespace Microsoft.AspNetCore.Mvc
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns> /// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
[NonAction] [NonAction]
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues) public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues)
=> RedirectToPagePermanent(pageName, routeValues, fragment: null); => RedirectToPagePermanent(pageName, pageHandler: null, routeValues: routeValues, fragment: null);
/// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="pageHandler"/>.
/// </summary>
/// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
[NonAction]
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string pageHandler)
=> RedirectToPagePermanent(pageName, routeValues: null);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="fragment"/>. /// using the specified <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns> /// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
[NonAction] [NonAction]
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string fragment) public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string pageHandler, string fragment)
=> RedirectToPagePermanent(pageName, routeValues: null, fragment: fragment); => RedirectToPagePermanent(pageName, pageHandler, routeValues: null, fragment: fragment);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>. /// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for a route.</param> /// <param name="routeValues">The parameters for a route.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns> /// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
[NonAction] [NonAction]
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues, string fragment) public virtual RedirectToPageResult RedirectToPagePermanent(
=> new RedirectToPageResult(pageName, routeValues, permanent: true, fragment: fragment); string pageName,
string pageHandler,
object routeValues,
string fragment)
{
return new RedirectToPageResult(pageName, pageHandler, routeValues, permanent: true, fragment: fragment);
}
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status307TemporaryRedirect"/>) to the specified page with /// Redirects (<see cref="StatusCodes.Status307TemporaryRedirect"/>) to the specified page with
@ -1035,12 +1078,14 @@ namespace Microsoft.AspNetCore.Mvc
/// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>. /// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The route data to use for generating the URL.</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> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns> /// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns>
[NonAction] [NonAction]
public virtual RedirectToPageResult RedirectToPagePreserveMethod( public virtual RedirectToPageResult RedirectToPagePreserveMethod(
string pageName, string pageName,
string pageHandler = null,
object routeValues = null, object routeValues = null,
string fragment = null) string fragment = null)
{ {
@ -1051,6 +1096,7 @@ namespace Microsoft.AspNetCore.Mvc
return new RedirectToPageResult( return new RedirectToPageResult(
pageName: pageName, pageName: pageName,
pageHandler: pageHandler,
routeValues: routeValues, routeValues: routeValues,
permanent: false, permanent: false,
preserveMethod: true, preserveMethod: true,
@ -1063,12 +1109,14 @@ namespace Microsoft.AspNetCore.Mvc
/// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>. /// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The route data to use for generating the URL.</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> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns> /// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns>
[NonAction] [NonAction]
public virtual RedirectToPageResult RedirectToPagePermanentPreserveMethod( public virtual RedirectToPageResult RedirectToPagePermanentPreserveMethod(
string pageName, string pageName,
string pageHandler = null,
object routeValues = null, object routeValues = null,
string fragment = null) string fragment = null)
{ {
@ -1079,6 +1127,7 @@ namespace Microsoft.AspNetCore.Mvc
return new RedirectToPageResult( return new RedirectToPageResult(
pageName: pageName, pageName: pageName,
pageHandler: pageHandler,
routeValues: routeValues, routeValues: routeValues,
permanent: true, permanent: true,
preserveMethod: true, preserveMethod: true,

View File

@ -36,6 +36,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
var urlHelper = result.UrlHelper ?? _urlHelperFactory.GetUrlHelper(context); var urlHelper = result.UrlHelper ?? _urlHelperFactory.GetUrlHelper(context);
var destinationUrl = urlHelper.Page( var destinationUrl = urlHelper.Page(
result.PageName, result.PageName,
result.PageHandler,
result.RouteValues, result.RouteValues,
result.Protocol, result.Protocol,
result.Host, result.Host,

View File

@ -26,6 +26,17 @@ namespace Microsoft.AspNetCore.Mvc
{ {
} }
/// <summary>
/// Initializes a new instance of the <see cref="RedirectToPageResult"/> with the values
/// provided.
/// </summary>
/// <param name="pageName">The page to redirect to.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
public RedirectToPageResult(string pageName, string pageHandler)
: this(pageName, pageHandler, routeValues: null)
{
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RedirectToPageResult"/> with the values /// Initializes a new instance of the <see cref="RedirectToPageResult"/> with the values
/// provided. /// provided.
@ -33,7 +44,19 @@ namespace Microsoft.AspNetCore.Mvc
/// <param name="pageName">The page to redirect to.</param> /// <param name="pageName">The page to redirect to.</param>
/// <param name="routeValues">The parameters for the route.</param> /// <param name="routeValues">The parameters for the route.</param>
public RedirectToPageResult(string pageName, object routeValues) public RedirectToPageResult(string pageName, object routeValues)
: this(pageName, routeValues, permanent: false) : this(pageName, pageHandler: null, routeValues: routeValues, permanent: false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RedirectToPageResult"/> with the values
/// provided.
/// </summary>
/// <param name="pageName">The page to redirect to.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for the route.</param>
public RedirectToPageResult(string pageName, string pageHandler, object routeValues)
: this(pageName, pageHandler, routeValues, permanent: false)
{ {
} }
@ -42,13 +65,15 @@ namespace Microsoft.AspNetCore.Mvc
/// provided. /// provided.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for the page.</param> /// <param name="routeValues">The parameters for the page.</param>
/// <param name="permanent">If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302).</param> /// <param name="permanent">If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302).</param>
public RedirectToPageResult( public RedirectToPageResult(
string pageName, string pageName,
string pageHandler,
object routeValues, object routeValues,
bool permanent) bool permanent)
: this(pageName, routeValues, permanent, fragment: null) : this(pageName, pageHandler, routeValues, permanent, fragment: null)
{ {
} }
@ -56,15 +81,17 @@ namespace Microsoft.AspNetCore.Mvc
/// Initializes a new instance of the <see cref="RedirectToPageResult"/> with the values provided. /// Initializes a new instance of the <see cref="RedirectToPageResult"/> with the values provided.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for the page.</param> /// <param name="routeValues">The parameters for the page.</param>
/// <param name="permanent">If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302).</param> /// <param name="permanent">If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302).</param>
/// <param name="preserveMethod">If set to true, make the temporary redirect (307) or permanent redirect (308) preserve the intial request method.</param> /// <param name="preserveMethod">If set to true, make the temporary redirect (307) or permanent redirect (308) preserve the intial request method.</param>
public RedirectToPageResult( public RedirectToPageResult(
string pageName, string pageName,
string pageHandler,
object routeValues, object routeValues,
bool permanent, bool permanent,
bool preserveMethod) bool preserveMethod)
: this(pageName, routeValues, permanent, preserveMethod, fragment: null) : this(pageName, pageHandler, routeValues, permanent, preserveMethod, fragment: null)
{ {
} }
@ -73,13 +100,15 @@ namespace Microsoft.AspNetCore.Mvc
/// provided. /// provided.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for the route.</param> /// <param name="routeValues">The parameters for the route.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
public RedirectToPageResult( public RedirectToPageResult(
string pageName, string pageName,
string pageHandler,
object routeValues, object routeValues,
string fragment) string fragment)
: this(pageName, routeValues, permanent: false, fragment: fragment) : this(pageName, pageHandler, routeValues, permanent: false, fragment: fragment)
{ {
} }
@ -88,19 +117,19 @@ namespace Microsoft.AspNetCore.Mvc
/// provided. /// provided.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for the page.</param> /// <param name="routeValues">The parameters for the page.</param>
/// <param name="permanent">If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302).</param> /// <param name="permanent">If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302).</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
public RedirectToPageResult( public RedirectToPageResult(
string pageName, string pageName,
string pageHandler,
object routeValues, object routeValues,
bool permanent, bool permanent,
string fragment) string fragment)
: this(pageName, pageHandler, routeValues, permanent, preserveMethod: false, fragment: fragment)
{ {
PageName = pageName;
RouteValues = routeValues == null ? new RouteValueDictionary() : new RouteValueDictionary(routeValues);
Permanent = permanent;
Fragment = fragment;
} }
/// <summary> /// <summary>
@ -108,18 +137,21 @@ namespace Microsoft.AspNetCore.Mvc
/// provided. /// provided.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for the page.</param> /// <param name="routeValues">The parameters for the page.</param>
/// <param name="permanent">If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302).</param> /// <param name="permanent">If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302).</param>
/// <param name="preserveMethod">If set to true, make the temporary redirect (307) or permanent redirect (308) preserve the intial request method.</param> /// <param name="preserveMethod">If set to true, make the temporary redirect (307) or permanent redirect (308) preserve the intial request method.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
public RedirectToPageResult( public RedirectToPageResult(
string pageName, string pageName,
string pageHandler,
object routeValues, object routeValues,
bool permanent, bool permanent,
bool preserveMethod, bool preserveMethod,
string fragment) string fragment)
{ {
PageName = pageName; PageName = pageName;
PageHandler = pageHandler;
RouteValues = routeValues == null ? null : new RouteValueDictionary(routeValues); RouteValues = routeValues == null ? null : new RouteValueDictionary(routeValues);
PreserveMethod = preserveMethod; PreserveMethod = preserveMethod;
Permanent = permanent; Permanent = permanent;
@ -136,6 +168,11 @@ namespace Microsoft.AspNetCore.Mvc
/// </summary> /// </summary>
public string PageName { get; set; } public string PageName { get; set; }
/// <summary>
/// Gets or sets the the page handler to redirect to.
/// </summary>
public string PageHandler { get; set; }
/// <summary> /// <summary>
/// Gets or sets the route data to use for generating the URL. /// Gets or sets the route data to use for generating the URL.
/// </summary> /// </summary>

View File

@ -351,13 +351,10 @@ namespace Microsoft.AspNetCore.Mvc
/// </summary> /// </summary>
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param> /// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
/// <param name="pageName">The page name to generate the url for.</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="pageHandler">The handler to generate the url for.</param>
/// <returns>The generated URL.</returns> /// <returns>The generated URL.</returns>
public static string Page( public static string Page(this IUrlHelper urlHelper, string pageName, string pageHandler)
this IUrlHelper urlHelper, => Page(urlHelper, pageName, pageHandler, values: null);
string pageName,
object values)
=> Page(urlHelper, pageName, values, protocol: null);
/// <summary> /// <summary>
/// Generates a URL with an absolute path for the specified <paramref name="pageName"/>. /// Generates a URL with an absolute path for the specified <paramref name="pageName"/>.
@ -365,20 +362,48 @@ namespace Microsoft.AspNetCore.Mvc
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param> /// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
/// <param name="pageName">The page name to generate the url for.</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="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, pageHandler: null, values: values);
/// <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="pageHandler">The handler 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,
string pageHandler,
object values)
=> Page(urlHelper, pageName, pageHandler, 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="pageHandler">The handler 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="protocol">The protocol for the URL, such as "http" or "https".</param>
/// <returns>The generated URL.</returns> /// <returns>The generated URL.</returns>
public static string Page( public static string Page(
this IUrlHelper urlHelper, this IUrlHelper urlHelper,
string pageName, string pageName,
string pageHandler,
object values, object values,
string protocol) string protocol)
=> Page(urlHelper, pageName, values, protocol, host: null, fragment: null); => Page(urlHelper, pageName, pageHandler, values, protocol, host: null, fragment: null);
/// <summary> /// <summary>
/// Generates a URL with an absolute path for the specified <paramref name="pageName"/>. /// Generates a URL with an absolute path for the specified <paramref name="pageName"/>.
/// </summary> /// </summary>
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param> /// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
/// <param name="pageName">The page name to generate the url for.</param> /// <param name="pageName">The page name to generate the url for.</param>
/// <param name="pageHandler">The handler to generate the url for.</param>
/// <param name="values">An object that contains route values.</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="protocol">The protocol for the URL, such as "http" or "https".</param>
/// <param name="host">The host name for the URL.</param> /// <param name="host">The host name for the URL.</param>
@ -386,16 +411,18 @@ namespace Microsoft.AspNetCore.Mvc
public static string Page( public static string Page(
this IUrlHelper urlHelper, this IUrlHelper urlHelper,
string pageName, string pageName,
string pageHandler,
object values, object values,
string protocol, string protocol,
string host) string host)
=> Page(urlHelper, pageName, values, protocol, host, fragment: null); => Page(urlHelper, pageName, pageHandler, values, protocol, host, fragment: null);
/// <summary> /// <summary>
/// Generates a URL with an absolute path for the specified <paramref name="pageName"/>. /// Generates a URL with an absolute path for the specified <paramref name="pageName"/>.
/// </summary> /// </summary>
/// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param> /// <param name="urlHelper">The <see cref="IUrlHelper"/>.</param>
/// <param name="pageName">The page name to generate the url for.</param> /// <param name="pageName">The page name to generate the url for.</param>
/// <param name="pageHandler">The handler to generate the url for.</param>
/// <param name="values">An object that contains route values.</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="protocol">The protocol for the URL, such as "http" or "https".</param>
/// <param name="host">The host name for the URL.</param> /// <param name="host">The host name for the URL.</param>
@ -404,6 +431,7 @@ namespace Microsoft.AspNetCore.Mvc
public static string Page( public static string Page(
this IUrlHelper urlHelper, this IUrlHelper urlHelper,
string pageName, string pageName,
string pageHandler,
object values, object values,
string protocol, string protocol,
string host, string host,
@ -429,11 +457,18 @@ namespace Microsoft.AspNetCore.Mvc
routeValues["page"] = CalculatePageName(urlHelper.ActionContext, pageName); routeValues["page"] = CalculatePageName(urlHelper.ActionContext, pageName);
} }
if (!routeValues.ContainsKey("handler") && if (string.IsNullOrEmpty(pageHandler))
ambientValues.TryGetValue("handler", out var handler))
{ {
// Clear out handler unless it's explicitly specified in the routeValues. if (!routeValues.ContainsKey("handler") &&
routeValues["handler"] = null; ambientValues.TryGetValue("handler", out var handler))
{
// Clear out formaction unless it's explicitly specified in the routeValues.
routeValues["handler"] = null;
}
}
else
{
routeValues["handler"] = pageHandler;
} }
return urlHelper.RouteUrl( return urlHelper.RouteUrl(

View File

@ -160,7 +160,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
} }
} }
#region Factory methods
/// <summary> /// <summary>
/// Creates a <see cref="ChallengeResult"/>. /// Creates a <see cref="ChallengeResult"/>.
/// </summary> /// </summary>
@ -970,6 +969,16 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
public virtual RedirectToPageResult RedirectToPage(string pageName) public virtual RedirectToPageResult RedirectToPage(string pageName)
=> RedirectToPage(pageName, routeValues: null); => RedirectToPage(pageName, routeValues: null);
/// <summary>
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="pageHandler"/>.
/// </summary>
/// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
public virtual RedirectToPageResult RedirectToPage(string pageName, string pageHandler)
=> RedirectToPage(pageName, routeValues: null);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="routeValues"/>. /// using the specified <paramref name="routeValues"/>.
@ -978,28 +987,30 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
/// <param name="routeValues">The parameters for a route.</param> /// <param name="routeValues">The parameters for a route.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns> /// <returns>The <see cref="RedirectToPageResult"/>.</returns>
public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues) public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues)
=> RedirectToPage(pageName, routeValues, fragment: null); => RedirectToPage(pageName, pageHandler: null, routeValues: routeValues, fragment: null);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="fragment"/>. /// using the specified <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns> /// <returns>The <see cref="RedirectToPageResult"/>.</returns>
public virtual RedirectToPageResult RedirectToPage(string pageName, string fragment) public virtual RedirectToPageResult RedirectToPage(string pageName, string pageHandler, string fragment)
=> RedirectToPage(pageName, routeValues: null, fragment: fragment); => RedirectToPage(pageName, pageHandler, routeValues: null, fragment: fragment);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>. /// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for a route.</param> /// <param name="routeValues">The parameters for a route.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns> /// <returns>The <see cref="RedirectToPageResult"/>.</returns>
public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues, string fragment) public virtual RedirectToPageResult RedirectToPage(string pageName, string pageHandler, object routeValues, string fragment)
=> new RedirectToPageResult(pageName, routeValues, fragment); => new RedirectToPageResult(pageName, pageHandler, routeValues, fragment);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>. /// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>.
@ -1007,7 +1018,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns> /// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName) public virtual RedirectToPageResult RedirectToPagePermanent(string pageName)
=> RedirectToPagePermanent(pageName, routeValues: null); => RedirectToPagePermanent(pageName, pageHandler: null);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>
@ -1017,28 +1028,51 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
/// <param name="routeValues">The parameters for a route.</param> /// <param name="routeValues">The parameters for a route.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns> /// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues) public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues)
=> RedirectToPagePermanent(pageName, routeValues, fragment: null); => RedirectToPagePermanent(pageName, pageHandler: null, routeValues: routeValues, fragment: null);
/// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="pageHandler"/>.
/// </summary>
/// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string pageHandler)
=> RedirectToPagePermanent(pageName, pageHandler, 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="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for a route.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string pageHandler, object routeValues)
=> RedirectToPagePermanent(pageName, pageHandler, routeValues, fragment: null);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="fragment"/>. /// using the specified <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns> /// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string fragment) public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string pageHandler, string fragment)
=> RedirectToPagePermanent(pageName, routeValues: null, fragment: fragment); => RedirectToPagePermanent(pageName, pageHandler, routeValues: null, fragment: fragment);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>. /// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for a route.</param> /// <param name="routeValues">The parameters for a route.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns> /// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
protected RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues, string fragment) protected RedirectToPageResult RedirectToPagePermanent(string pageName, string pageHandler, object routeValues, string fragment)
=> new RedirectToPageResult(pageName, routeValues, permanent: true, fragment: fragment); => new RedirectToPageResult(pageName, pageHandler, routeValues, permanent: true, fragment: fragment);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status307TemporaryRedirect"/>) to the specified page with /// Redirects (<see cref="StatusCodes.Status307TemporaryRedirect"/>) to the specified page with
@ -1046,16 +1080,19 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
/// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>. /// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The route data to use for generating the URL.</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> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns> /// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns>
public virtual RedirectToPageResult RedirectToPagePreserveMethod( public virtual RedirectToPageResult RedirectToPagePreserveMethod(
string pageName = null, string pageName = null,
string pageHandler = null,
object routeValues = null, object routeValues = null,
string fragment = null) string fragment = null)
{ {
return new RedirectToPageResult( return new RedirectToPageResult(
pageName: pageName, pageName: pageName,
pageHandler: pageHandler,
routeValues: routeValues, routeValues: routeValues,
permanent: false, permanent: false,
preserveMethod: true, preserveMethod: true,
@ -1068,16 +1105,19 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
/// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>. /// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The route data to use for generating the URL.</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> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns> /// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns>
public virtual RedirectToPageResult RedirectToPagePermanentPreserveMethod( public virtual RedirectToPageResult RedirectToPagePermanentPreserveMethod(
string pageName = null, string pageName = null,
string pageHandler = null,
object routeValues = null, object routeValues = null,
string fragment = null) string fragment = null)
{ {
return new RedirectToPageResult( return new RedirectToPageResult(
pageName: pageName, pageName: pageName,
pageHandler: pageHandler,
routeValues: routeValues, routeValues: routeValues,
permanent: true, permanent: true,
preserveMethod: true, preserveMethod: true,
@ -1157,11 +1197,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
/// Returning a <see cref="PageViewResult"/> from a page handler method is equivalent to returning void. /// Returning a <see cref="PageViewResult"/> from a page handler method is equivalent to returning void.
/// The view associated with the page will be executed. /// The view associated with the page will be executed.
/// </remarks> /// </remarks>
protected PageViewResult View() protected PageViewResult View() => new PageViewResult(this);
{
return new PageViewResult(this);
}
#endregion Factory methods
/// <summary> /// <summary>
/// Updates the specified <paramref name="model"/> instance using values from the <see cref="Page"/>'s current /// Updates the specified <paramref name="model"/> instance using values from the <see cref="Page"/>'s current

View File

@ -488,7 +488,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
propertyFilter); propertyFilter);
} }
#region Factory methods
/// <summary> /// <summary>
/// Creates a <see cref="ChallengeResult"/>. /// Creates a <see cref="ChallengeResult"/>.
/// </summary> /// </summary>
@ -1298,9 +1297,30 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns> /// <returns>The <see cref="RedirectToPageResult"/>.</returns>
protected internal RedirectToPageResult RedirectToPage(string pageName) public virtual RedirectToPageResult RedirectToPage(string pageName)
=> RedirectToPage(pageName, routeValues: null); => RedirectToPage(pageName, routeValues: null);
/// <summary>
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="pageHandler"/>.
/// </summary>
/// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
public virtual RedirectToPageResult RedirectToPage(string pageName, string pageHandler)
=> RedirectToPage(pageName, pageHandler, routeValues: null);
/// <summary>
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="pageHandler"/> and <paramref name="routeValues"/>.
/// </summary>
/// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for a route.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns>
public virtual RedirectToPageResult RedirectToPage(string pageName, string pageHandler, object routeValues)
=> RedirectToPage(pageName, pageHandler, routeValues, fragment: null);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="routeValues"/>. /// using the specified <paramref name="routeValues"/>.
@ -1308,37 +1328,39 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="routeValues">The parameters for a route.</param> /// <param name="routeValues">The parameters for a route.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns> /// <returns>The <see cref="RedirectToPageResult"/>.</returns>
protected internal RedirectToPageResult RedirectToPage(string pageName, object routeValues) public virtual RedirectToPageResult RedirectToPage(string pageName, object routeValues)
=> RedirectToPage(pageName, routeValues, fragment: null); => RedirectToPage(pageName, pageHandler: null, routeValues: routeValues, fragment: null);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="fragment"/>. /// using the specified <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns> /// <returns>The <see cref="RedirectToPageResult"/>.</returns>
protected internal RedirectToPageResult RedirectToPage(string pageName, string fragment) public virtual RedirectToPageResult RedirectToPage(string pageName, string pageHandler, string fragment)
=> RedirectToPage(pageName, routeValues: null, fragment: fragment); => RedirectToPage(pageName, pageHandler, routeValues: null, fragment: fragment);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status302Found"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>. /// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for a route.</param> /// <param name="routeValues">The parameters for a route.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The <see cref="RedirectToPageResult"/>.</returns> /// <returns>The <see cref="RedirectToPageResult"/>.</returns>
protected internal RedirectToPageResult RedirectToPage(string pageName, object routeValues, string fragment) public virtual RedirectToPageResult RedirectToPage(string pageName, string pageHandler, object routeValues, string fragment)
=> new RedirectToPageResult(pageName, routeValues, fragment); => new RedirectToPageResult(pageName, pageHandler, routeValues, fragment);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>. /// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns> /// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
protected internal RedirectToPageResult RedirectToPagePermanent(string pageName) public virtual RedirectToPageResult RedirectToPagePermanent(string pageName)
=> RedirectToPagePermanent(pageName, routeValues: null); => RedirectToPagePermanent(pageName, pageHandler: null);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>
@ -1347,29 +1369,62 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="routeValues">The parameters for a route.</param> /// <param name="routeValues">The parameters for a route.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns> /// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
protected internal RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues) public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues)
=> RedirectToPagePermanent(pageName, routeValues, fragment: null); => RedirectToPagePermanent(pageName, pageHandler: null, routeValues: routeValues, fragment: null);
/// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>.
/// </summary>
/// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string pageHandler)
=> RedirectToPagePermanent(pageName, pageHandler, 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="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for a route.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string pageHandler, object routeValues)
=> RedirectToPagePermanent(pageName, pageHandler, routeValues, fragment: null);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="fragment"/>. /// using the specified <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns> /// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
protected internal RedirectToPageResult RedirectToPagePermanent(string pageName, string fragment) public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string pageHandler, string fragment)
=> RedirectToPagePermanent(pageName, routeValues: null, fragment: fragment); => RedirectToPagePermanent(pageName, pageHandler, routeValues: null, fragment: fragment);
/// <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="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>
public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues, string fragment)
=> RedirectToPagePermanent(pageName, pageHandler: null, routeValues: routeValues, fragment: fragment);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/> /// Redirects (<see cref="StatusCodes.Status301MovedPermanently"/>) to the specified <paramref name="pageName"/>
/// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>. /// using the specified <paramref name="routeValues"/> and <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The parameters for a route.</param> /// <param name="routeValues">The parameters for a route.</param>
/// <param name="fragment">The fragment to add to the URL.</param> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns> /// <returns>The <see cref="RedirectToPageResult"/> with <see cref="RedirectToPageResult.Permanent"/> set.</returns>
protected internal RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues, string fragment) public virtual RedirectToPageResult RedirectToPagePermanent(string pageName, string pageHandler, object routeValues, string fragment)
=> new RedirectToPageResult(pageName, routeValues, permanent: true, fragment: fragment); => new RedirectToPageResult(pageName, pageHandler, routeValues, permanent: true, fragment: fragment);
/// <summary> /// <summary>
/// Redirects (<see cref="StatusCodes.Status307TemporaryRedirect"/>) to the specified page with /// Redirects (<see cref="StatusCodes.Status307TemporaryRedirect"/>) to the specified page with
@ -1377,16 +1432,19 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
/// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>. /// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The route data to use for generating the URL.</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> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns> /// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns>
public virtual RedirectToPageResult RedirectToPagePreserveMethod( public virtual RedirectToPageResult RedirectToPagePreserveMethod(
string pageName = null, string pageName = null,
string pageHandler = null,
object routeValues = null, object routeValues = null,
string fragment = null) string fragment = null)
{ {
return new RedirectToPageResult( return new RedirectToPageResult(
pageName: pageName, pageName: pageName,
pageHandler: pageHandler,
routeValues: routeValues, routeValues: routeValues,
permanent: false, permanent: false,
preserveMethod: true, preserveMethod: true,
@ -1399,16 +1457,19 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
/// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>. /// set to true, using the specified <paramref name="pageName"/>, <paramref name="routeValues"/>, and <paramref name="fragment"/>.
/// </summary> /// </summary>
/// <param name="pageName">The name of the page.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to redirect to.</param>
/// <param name="routeValues">The route data to use for generating the URL.</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> /// <param name="fragment">The fragment to add to the URL.</param>
/// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns> /// <returns>The created <see cref="RedirectToRouteResult"/> for the response.</returns>
public virtual RedirectToPageResult RedirectToPagePermanentPreserveMethod( public virtual RedirectToPageResult RedirectToPagePermanentPreserveMethod(
string pageName = null, string pageName = null,
string pageHandler = null,
object routeValues = null, object routeValues = null,
string fragment = null) string fragment = null)
{ {
return new RedirectToPageResult( return new RedirectToPageResult(
pageName: pageName, pageName: pageName,
pageHandler: pageHandler,
routeValues: routeValues, routeValues: routeValues,
permanent: true, permanent: true,
preserveMethod: true, preserveMethod: true,
@ -1493,7 +1554,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
{ {
return new PageViewResult(Page); return new PageViewResult(Page);
} }
#endregion Factory methods
/// <summary> /// <summary>
/// Validates the specified <paramref name="model"/> instance. /// Validates the specified <paramref name="model"/> instance.

View File

@ -17,6 +17,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlTargetElement("a", Attributes = ControllerAttributeName)] [HtmlTargetElement("a", Attributes = ControllerAttributeName)]
[HtmlTargetElement("a", Attributes = AreaAttributeName)] [HtmlTargetElement("a", Attributes = AreaAttributeName)]
[HtmlTargetElement("a", Attributes = PageAttributeName)] [HtmlTargetElement("a", Attributes = PageAttributeName)]
[HtmlTargetElement("a", Attributes = PageHandlerAttributeName)]
[HtmlTargetElement("a", Attributes = FragmentAttributeName)] [HtmlTargetElement("a", Attributes = FragmentAttributeName)]
[HtmlTargetElement("a", Attributes = HostAttributeName)] [HtmlTargetElement("a", Attributes = HostAttributeName)]
[HtmlTargetElement("a", Attributes = ProtocolAttributeName)] [HtmlTargetElement("a", Attributes = ProtocolAttributeName)]
@ -29,6 +30,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
private const string ControllerAttributeName = "asp-controller"; private const string ControllerAttributeName = "asp-controller";
private const string AreaAttributeName = "asp-area"; private const string AreaAttributeName = "asp-area";
private const string PageAttributeName = "asp-page"; private const string PageAttributeName = "asp-page";
private const string PageHandlerAttributeName = "asp-page-handler";
private const string FragmentAttributeName = "asp-fragment"; private const string FragmentAttributeName = "asp-fragment";
private const string HostAttributeName = "asp-host"; private const string HostAttributeName = "asp-host";
private const string ProtocolAttributeName = "asp-protocol"; private const string ProtocolAttributeName = "asp-protocol";
@ -95,6 +97,16 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlAttributeName(PageAttributeName)] [HtmlAttributeName(PageAttributeName)]
public string Page { get; set; } public string Page { get; set; }
/// <summary>
/// The name of the page handler.
/// </summary>
/// <remarks>
/// Must be <c>null</c> if <see cref="Route"/> or <see cref="Action"/>, or <see cref="Controller"/>
/// is non-<c>null</c>.
/// </remarks>
[HtmlAttributeName(PageHandlerAttributeName)]
public string PageHandler { get; set; }
/// <summary> /// <summary>
/// The protocol for the URL, such as &quot;http&quot; or &quot;https&quot;. /// The protocol for the URL, such as &quot;http&quot; or &quot;https&quot;.
/// </summary> /// </summary>
@ -172,6 +184,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
Controller != null || Controller != null ||
Area != null || Area != null ||
Page != null || Page != null ||
PageHandler != null ||
Route != null || Route != null ||
Protocol != null || Protocol != null ||
Host != null || Host != null ||
@ -191,7 +204,8 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
ProtocolAttributeName, ProtocolAttributeName,
HostAttributeName, HostAttributeName,
FragmentAttributeName, FragmentAttributeName,
PageAttributeName)); PageAttributeName,
PageHandlerAttributeName));
} }
return; return;
@ -199,7 +213,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
var routeLink = Route != null; var routeLink = Route != null;
var actionLink = Controller != null || Action != null; var actionLink = Controller != null || Action != null;
var pageLink = Page != null; var pageLink = Page != null || PageHandler != null;
if ((routeLink && actionLink) || (routeLink && pageLink) || (actionLink && pageLink)) if ((routeLink && actionLink) || (routeLink && pageLink) || (actionLink && pageLink))
{ {
@ -208,7 +222,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
Resources.FormatCannotDetermineAttributeFor(Href, "<a>"), Resources.FormatCannotDetermineAttributeFor(Href, "<a>"),
RouteAttributeName, RouteAttributeName,
ControllerAttributeName + ", " + ActionAttributeName, ControllerAttributeName + ", " + ActionAttributeName,
PageAttributeName); PageAttributeName + ", " + PageHandlerAttributeName);
throw new InvalidOperationException(message); throw new InvalidOperationException(message);
} }
@ -236,6 +250,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
ViewContext, ViewContext,
linkText: string.Empty, linkText: string.Empty,
pageName: Page, pageName: Page,
pageHandler: PageHandler,
protocol: Protocol, protocol: Protocol,
hostname: Host, hostname: Host,
fragment: Fragment, fragment: Fragment,

View File

@ -19,6 +19,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlTargetElement("button", Attributes = ControllerAttributeName)] [HtmlTargetElement("button", Attributes = ControllerAttributeName)]
[HtmlTargetElement("button", Attributes = AreaAttributeName)] [HtmlTargetElement("button", Attributes = AreaAttributeName)]
[HtmlTargetElement("button", Attributes = PageAttributeName)] [HtmlTargetElement("button", Attributes = PageAttributeName)]
[HtmlTargetElement("button", Attributes = PageHandlerAttributeName)]
[HtmlTargetElement("button", Attributes = FragmentAttributeName)] [HtmlTargetElement("button", Attributes = FragmentAttributeName)]
[HtmlTargetElement("button", Attributes = RouteAttributeName)] [HtmlTargetElement("button", Attributes = RouteAttributeName)]
[HtmlTargetElement("button", Attributes = RouteValuesDictionaryName)] [HtmlTargetElement("button", Attributes = RouteValuesDictionaryName)]
@ -27,6 +28,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlTargetElement("input", Attributes = ImageControllerAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("input", Attributes = ImageControllerAttributeSelector, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("input", Attributes = ImageAreaAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("input", Attributes = ImageAreaAttributeSelector, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("input", Attributes = ImagePageAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("input", Attributes = ImagePageAttributeSelector, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("input", Attributes = ImagePageHandlerAttributeSelector, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("input", Attributes = ImageFragmentAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("input", Attributes = ImageFragmentAttributeSelector, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("input", Attributes = ImageRouteAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("input", Attributes = ImageRouteAttributeSelector, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("input", Attributes = ImageRouteValuesDictionarySelector, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("input", Attributes = ImageRouteValuesDictionarySelector, TagStructure = TagStructure.WithoutEndTag)]
@ -35,6 +37,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlTargetElement("input", Attributes = SubmitControllerAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("input", Attributes = SubmitControllerAttributeSelector, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("input", Attributes = SubmitAreaAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("input", Attributes = SubmitAreaAttributeSelector, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("input", Attributes = SubmitPageAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("input", Attributes = SubmitPageAttributeSelector, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("input", Attributes = SubmitPageHandlerAttributeSelector, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("input", Attributes = SubmitFragmentAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("input", Attributes = SubmitFragmentAttributeSelector, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("input", Attributes = SubmitRouteAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("input", Attributes = SubmitRouteAttributeSelector, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("input", Attributes = SubmitRouteValuesDictionarySelector, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("input", Attributes = SubmitRouteValuesDictionarySelector, TagStructure = TagStructure.WithoutEndTag)]
@ -45,6 +48,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
private const string AreaAttributeName = "asp-area"; private const string AreaAttributeName = "asp-area";
private const string ControllerAttributeName = "asp-controller"; private const string ControllerAttributeName = "asp-controller";
private const string PageAttributeName = "asp-page"; private const string PageAttributeName = "asp-page";
private const string PageHandlerAttributeName = "asp-page-handler";
private const string FragmentAttributeName = "asp-fragment"; private const string FragmentAttributeName = "asp-fragment";
private const string RouteAttributeName = "asp-route"; private const string RouteAttributeName = "asp-route";
private const string RouteValuesDictionaryName = "asp-all-route-data"; private const string RouteValuesDictionaryName = "asp-all-route-data";
@ -55,6 +59,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
private const string ImageActionAttributeSelector = ImageTypeSelector + ActionAttributeName; private const string ImageActionAttributeSelector = ImageTypeSelector + ActionAttributeName;
private const string ImageAreaAttributeSelector = ImageTypeSelector + AreaAttributeName; private const string ImageAreaAttributeSelector = ImageTypeSelector + AreaAttributeName;
private const string ImagePageAttributeSelector = ImageTypeSelector + PageAttributeName; private const string ImagePageAttributeSelector = ImageTypeSelector + PageAttributeName;
private const string ImagePageHandlerAttributeSelector = ImageTypeSelector + PageHandlerAttributeName;
private const string ImageFragmentAttributeSelector = ImageTypeSelector + FragmentAttributeName; private const string ImageFragmentAttributeSelector = ImageTypeSelector + FragmentAttributeName;
private const string ImageControllerAttributeSelector = ImageTypeSelector + ControllerAttributeName; private const string ImageControllerAttributeSelector = ImageTypeSelector + ControllerAttributeName;
private const string ImageRouteAttributeSelector = ImageTypeSelector + RouteAttributeName; private const string ImageRouteAttributeSelector = ImageTypeSelector + RouteAttributeName;
@ -65,6 +70,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
private const string SubmitActionAttributeSelector = SubmitTypeSelector + ActionAttributeName; private const string SubmitActionAttributeSelector = SubmitTypeSelector + ActionAttributeName;
private const string SubmitAreaAttributeSelector = SubmitTypeSelector + AreaAttributeName; private const string SubmitAreaAttributeSelector = SubmitTypeSelector + AreaAttributeName;
private const string SubmitPageAttributeSelector = SubmitTypeSelector + PageAttributeName; private const string SubmitPageAttributeSelector = SubmitTypeSelector + PageAttributeName;
private const string SubmitPageHandlerAttributeSelector = SubmitTypeSelector + PageHandlerAttributeName;
private const string SubmitFragmentAttributeSelector = SubmitTypeSelector + FragmentAttributeName; private const string SubmitFragmentAttributeSelector = SubmitTypeSelector + FragmentAttributeName;
private const string SubmitControllerAttributeSelector = SubmitTypeSelector + ControllerAttributeName; private const string SubmitControllerAttributeSelector = SubmitTypeSelector + ControllerAttributeName;
private const string SubmitRouteAttributeSelector = SubmitTypeSelector + RouteAttributeName; private const string SubmitRouteAttributeSelector = SubmitTypeSelector + RouteAttributeName;
@ -118,6 +124,12 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlAttributeName(PageAttributeName)] [HtmlAttributeName(PageAttributeName)]
public string Page { get; set; } public string Page { get; set; }
/// <summary>
/// The name of the page handler.
/// </summary>
[HtmlAttributeName(PageHandlerAttributeName)]
public string PageHandler { get; set; }
/// <summary> /// <summary>
/// Gets or sets the URL fragment. /// Gets or sets the URL fragment.
/// </summary> /// </summary>
@ -180,6 +192,8 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
if (Action != null || if (Action != null ||
Controller != null || Controller != null ||
Area != null || Area != null ||
Page != null ||
PageHandler != null ||
Fragment != null || Fragment != null ||
Route != null || Route != null ||
(_routeValues != null && _routeValues.Count > 0)) (_routeValues != null && _routeValues.Count > 0))
@ -188,14 +202,16 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
// attribute. // attribute.
throw new InvalidOperationException( throw new InvalidOperationException(
Resources.FormatFormActionTagHelper_CannotOverrideFormAction( Resources.FormatFormActionTagHelper_CannotOverrideFormAction(
FormAction,
output.TagName, output.TagName,
RouteValuesPrefix,
ActionAttributeName, ActionAttributeName,
ControllerAttributeName, ControllerAttributeName,
AreaAttributeName, AreaAttributeName,
FragmentAttributeName, FragmentAttributeName,
RouteAttributeName, RouteAttributeName,
RouteValuesPrefix, PageAttributeName,
FormAction)); PageHandlerAttributeName));
} }
return; return;
@ -203,7 +219,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
var routeLink = Route != null; var routeLink = Route != null;
var actionLink = Controller != null || Action != null; var actionLink = Controller != null || Action != null;
var pageLink = Page != null; var pageLink = Page != null || PageHandler != null;
if ((routeLink && actionLink) || (routeLink && pageLink) || (actionLink && pageLink)) if ((routeLink && actionLink) || (routeLink && pageLink) || (actionLink && pageLink))
{ {
@ -212,7 +228,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
Resources.FormatCannotDetermineAttributeFor(FormAction, '<' + output.TagName + '>'), Resources.FormatCannotDetermineAttributeFor(FormAction, '<' + output.TagName + '>'),
RouteAttributeName, RouteAttributeName,
ControllerAttributeName + ", " + ActionAttributeName, ControllerAttributeName + ", " + ActionAttributeName,
PageAttributeName); PageAttributeName + ", " + PageHandlerAttributeName);
throw new InvalidOperationException(message); throw new InvalidOperationException(message);
} }
@ -238,7 +254,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
string url; string url;
if (pageLink) if (pageLink)
{ {
url = urlHelper.Page(Page, routeValues, protocol: null, host: null, fragment: Fragment); url = urlHelper.Page(Page, PageHandler, routeValues, protocol: null, host: null, fragment: Fragment);
} }
else if (routeLink) else if (routeLink)
{ {

View File

@ -22,6 +22,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
private const string AntiforgeryAttributeName = "asp-antiforgery"; private const string AntiforgeryAttributeName = "asp-antiforgery";
private const string AreaAttributeName = "asp-area"; private const string AreaAttributeName = "asp-area";
private const string PageAttributeName = "asp-page"; private const string PageAttributeName = "asp-page";
private const string PageHandlerAttributeName = "asp-page-handler";
private const string FragmentAttributeName = "asp-fragment"; private const string FragmentAttributeName = "asp-fragment";
private const string ControllerAttributeName = "asp-controller"; private const string ControllerAttributeName = "asp-controller";
private const string RouteAttributeName = "asp-route"; private const string RouteAttributeName = "asp-route";
@ -74,6 +75,12 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlAttributeName(PageAttributeName)] [HtmlAttributeName(PageAttributeName)]
public string Page { get; set; } public string Page { get; set; }
/// <summary>
/// The name of the page handler.
/// </summary>
[HtmlAttributeName(PageHandlerAttributeName)]
public string PageHandler { get; set; }
/// <summary> /// <summary>
/// Whether the antiforgery token should be generated. /// Whether the antiforgery token should be generated.
/// </summary> /// </summary>
@ -164,6 +171,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
Controller != null || Controller != null ||
Area != null || Area != null ||
Page != null || Page != null ||
PageHandler != null ||
Fragment != null || Fragment != null ||
Route != null || Route != null ||
(_routeValues != null && _routeValues.Count > 0)) (_routeValues != null && _routeValues.Count > 0))
@ -179,7 +187,8 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
FragmentAttributeName, FragmentAttributeName,
AreaAttributeName, AreaAttributeName,
RouteAttributeName, RouteAttributeName,
PageAttributeName)); PageAttributeName,
PageHandlerAttributeName));
} }
string attributeValue = null; string attributeValue = null;
@ -210,7 +219,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
{ {
var routeLink = Route != null; var routeLink = Route != null;
var actionLink = Controller != null || Action != null; var actionLink = Controller != null || Action != null;
var pageLink = Page != null; var pageLink = Page != null || PageHandler != null;
if ((routeLink && actionLink) || (routeLink && pageLink) || (actionLink && pageLink)) if ((routeLink && actionLink) || (routeLink && pageLink) || (actionLink && pageLink))
{ {
@ -259,6 +268,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
tagBuilder = Generator.GeneratePageForm( tagBuilder = Generator.GeneratePageForm(
ViewContext, ViewContext,
Page, Page,
PageHandler,
routeValues, routeValues,
Fragment, Fragment,
method: null, method: null,

View File

@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
=> string.Format(CultureInfo.CurrentCulture, GetString("CannotDetermineAttributeFor"), p0, p1); => string.Format(CultureInfo.CurrentCulture, GetString("CannotDetermineAttributeFor"), p0, p1);
/// <summary> /// <summary>
/// Cannot override the '{0}' attribute for {1}. An {1} with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', or '{10}' attribute. /// Cannot override the '{0}' attribute for {1}. An {1} with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', '{10}' or '{11}' attribute.
/// </summary> /// </summary>
internal static string AnchorTagHelper_CannotOverrideHref internal static string AnchorTagHelper_CannotOverrideHref
{ {
@ -33,13 +33,13 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
} }
/// <summary> /// <summary>
/// Cannot override the '{0}' attribute for {1}. An {1} with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', or '{10}' attribute. /// Cannot override the '{0}' attribute for {1}. An {1} with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', '{10}' or '{11}' attribute.
/// </summary> /// </summary>
internal static string FormatAnchorTagHelper_CannotOverrideHref(object p0, object p1, object p2, object p3, object p4, object p5, object p6, object p7, object p8, object p9, object p10) internal static string FormatAnchorTagHelper_CannotOverrideHref(object p0, object p1, object p2, object p3, object p4, object p5, object p6, object p7, object p8, object p9, object p10, object p11)
=> string.Format(CultureInfo.CurrentCulture, GetString("AnchorTagHelper_CannotOverrideHref"), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); => string.Format(CultureInfo.CurrentCulture, GetString("AnchorTagHelper_CannotOverrideHref"), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
/// <summary> /// <summary>
/// Cannot override the '{0}' attribute for {1}. A {1} with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}' or '{8}' attribute. /// Cannot override the '{0}' attribute for {1}. A {1} with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}', '{8}' or '{9}' attribute.
/// </summary> /// </summary>
internal static string FormTagHelper_CannotOverrideAction internal static string FormTagHelper_CannotOverrideAction
{ {
@ -47,10 +47,10 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
} }
/// <summary> /// <summary>
/// Cannot override the '{0}' attribute for {1}. A {1} with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}' or '{8}' attribute. /// Cannot override the '{0}' attribute for {1}. A {1} with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}', '{8}' or '{9}' attribute.
/// </summary> /// </summary>
internal static string FormatFormTagHelper_CannotOverrideAction(object p0, object p1, object p2, object p3, object p4, object p5, object p6, object p7, object p8) internal static string FormatFormTagHelper_CannotOverrideAction(object p0, object p1, object p2, object p3, object p4, object p5, object p6, object p7, object p8, object p9)
=> string.Format(CultureInfo.CurrentCulture, GetString("FormTagHelper_CannotOverrideAction"), p0, p1, p2, p3, p4, p5, p6, p7, p8); => string.Format(CultureInfo.CurrentCulture, GetString("FormTagHelper_CannotOverrideAction"), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
/// <summary> /// <summary>
/// Unexpected '{1}' expression result type '{2}' for {0}. '{1}' must be of type '{3}' or '{4}' that can be parsed as a '{3}' if '{5}' is '{6}'. /// Unexpected '{1}' expression result type '{2}' for {0}. '{1}' must be of type '{3}' or '{4}' that can be parsed as a '{3}' if '{5}' is '{6}'.
@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
=> string.Format(CultureInfo.CurrentCulture, GetString("PropertyOfTypeCannotBeNull"), p0, p1); => string.Format(CultureInfo.CurrentCulture, GetString("PropertyOfTypeCannotBeNull"), p0, p1);
/// <summary> /// <summary>
/// Cannot override the '{7}' attribute for &lt;{0}&gt;. &lt;{0}&gt; elements with a specified '{7}' must not have attributes starting with '{6}' or an '{1}', '{2}', '{3}', '{4}', or '{5}' attribute. /// Cannot override the '{0}' attribute for &lt;{1}&gt;. &lt;{1}&gt; elements with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}', '{8}' or '{9}' attribute.
/// </summary> /// </summary>
internal static string FormActionTagHelper_CannotOverrideFormAction internal static string FormActionTagHelper_CannotOverrideFormAction
{ {
@ -159,10 +159,10 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
} }
/// <summary> /// <summary>
/// Cannot override the '{7}' attribute for &lt;{0}&gt;. &lt;{0}&gt; elements with a specified '{7}' must not have attributes starting with '{6}' or an '{1}', '{2}', '{3}', '{4}', or '{5}' attribute. /// Cannot override the '{0}' attribute for &lt;{1}&gt;. &lt;{1}&gt; elements with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}', '{8}' or '{9}' attribute.
/// </summary> /// </summary>
internal static string FormatFormActionTagHelper_CannotOverrideFormAction(object p0, object p1, object p2, object p3, object p4, object p5, object p6, object p7) internal static string FormatFormActionTagHelper_CannotOverrideFormAction(object p0, object p1, object p2, object p3, object p4, object p5, object p6, object p7, object p8, object p9)
=> string.Format(CultureInfo.CurrentCulture, GetString("FormActionTagHelper_CannotOverrideFormAction"), p0, p1, p2, p3, p4, p5, p6, p7); => string.Format(CultureInfo.CurrentCulture, GetString("FormActionTagHelper_CannotOverrideFormAction"), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
private static string GetString(string name, params string[] formatterNames) private static string GetString(string name, params string[] formatterNames)
{ {

View File

@ -121,10 +121,10 @@
<value>Cannot determine the '{0}' attribute for {1}. The following attributes are mutually exclusive:</value> <value>Cannot determine the '{0}' attribute for {1}. The following attributes are mutually exclusive:</value>
</data> </data>
<data name="AnchorTagHelper_CannotOverrideHref" xml:space="preserve"> <data name="AnchorTagHelper_CannotOverrideHref" xml:space="preserve">
<value>Cannot override the '{0}' attribute for {1}. An {1} with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', or '{10}' attribute.</value> <value>Cannot override the '{0}' attribute for {1}. An {1} with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', '{10}' or '{11}' attribute.</value>
</data> </data>
<data name="FormTagHelper_CannotOverrideAction" xml:space="preserve"> <data name="FormTagHelper_CannotOverrideAction" xml:space="preserve">
<value>Cannot override the '{0}' attribute for {1}. A {1} with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}' or '{8}' attribute.</value> <value>Cannot override the '{0}' attribute for {1}. A {1} with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}', '{8}' or '{9}' attribute.</value>
</data> </data>
<data name="InputTagHelper_InvalidExpressionResult" xml:space="preserve"> <data name="InputTagHelper_InvalidExpressionResult" xml:space="preserve">
<value>Unexpected '{1}' expression result type '{2}' for {0}. '{1}' must be of type '{3}' or '{4}' that can be parsed as a '{3}' if '{5}' is '{6}'.</value> <value>Unexpected '{1}' expression result type '{2}' for {0}. '{1}' must be of type '{3}' or '{4}' that can be parsed as a '{3}' if '{5}' is '{6}'.</value>
@ -148,6 +148,6 @@
<value>The '{0}' property of '{1}' must not be null.</value> <value>The '{0}' property of '{1}' must not be null.</value>
</data> </data>
<data name="FormActionTagHelper_CannotOverrideFormAction" xml:space="preserve"> <data name="FormActionTagHelper_CannotOverrideFormAction" xml:space="preserve">
<value>Cannot override the '{7}' attribute for &lt;{0}&gt;. &lt;{0}&gt; elements with a specified '{7}' must not have attributes starting with '{6}' or an '{1}', '{2}', '{3}', '{4}', or '{5}' attribute.</value> <value>Cannot override the '{0}' attribute for &lt;{1}&gt;. &lt;{1}&gt; elements with a specified '{0}' must not have attributes starting with '{2}' or an '{3}', '{4}', '{5}', '{6}', '{7}', '{8}' or '{9}' attribute.</value>
</data> </data>
</root> </root>

View File

@ -147,6 +147,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
ViewContext viewContext, ViewContext viewContext,
string linkText, string linkText,
string pageName, string pageName,
string pageHandler,
string protocol, string protocol,
string hostname, string hostname,
string fragment, string fragment,
@ -164,7 +165,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
} }
var urlHelper = _urlHelperFactory.GetUrlHelper(viewContext); var urlHelper = _urlHelperFactory.GetUrlHelper(viewContext);
var url = urlHelper.Page(pageName, routeValues, protocol, hostname, fragment); var url = urlHelper.Page(pageName, pageHandler, routeValues, protocol, hostname, fragment);
return GenerateLink(linkText, url, htmlAttributes); return GenerateLink(linkText, url, htmlAttributes);
} }
@ -311,6 +312,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
public virtual TagBuilder GeneratePageForm( public virtual TagBuilder GeneratePageForm(
ViewContext viewContext, ViewContext viewContext,
string pageName, string pageName,
string pageHandler,
object routeValues, object routeValues,
string fragment, string fragment,
string method, string method,
@ -347,7 +349,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
else else
{ {
var urlHelper = _urlHelperFactory.GetUrlHelper(viewContext); var urlHelper = _urlHelperFactory.GetUrlHelper(viewContext);
action = urlHelper.Page(pageName, values: routeValues,protocol: null, host: null, fragment: fragment); action = urlHelper.Page(pageName, pageHandler, routeValues, protocol: null, host: null, fragment: fragment);
} }
return GenerateFormCore(viewContext, action, method, htmlAttributes); return GenerateFormCore(viewContext, action, method, htmlAttributes);

View File

@ -60,6 +60,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
/// <param name="viewContext">The <see cref="ViewContext"/> instance for the current scope.</param> /// <param name="viewContext">The <see cref="ViewContext"/> instance for the current scope.</param>
/// <param name="linkText">The text to insert inside the element.</param> /// <param name="linkText">The text to insert inside the element.</param>
/// <param name="pageName">The page name.</param> /// <param name="pageName">The page name.</param>
/// <param name="pageHandler">The page handler.</param>
/// <param name="protocol">The protocol (scheme) for the generated link.</param> /// <param name="protocol">The protocol (scheme) for the generated link.</param>
/// <param name="hostname">The hostname for the generated link.</param> /// <param name="hostname">The hostname for the generated link.</param>
/// <param name="fragment">The fragment for the genrated link.</param> /// <param name="fragment">The fragment for the genrated link.</param>
@ -80,6 +81,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
ViewContext viewContext, ViewContext viewContext,
string linkText, string linkText,
string pageName, string pageName,
string pageHandler,
string protocol, string protocol,
string hostname, string hostname,
string fragment, string fragment,
@ -161,7 +163,8 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
/// <paramref name="pageName"/> will process the request. /// <paramref name="pageName"/> will process the request.
/// </summary> /// </summary>
/// <param name="viewContext">A <see cref="ViewContext"/> instance for the current scope.</param> /// <param name="viewContext">A <see cref="ViewContext"/> instance for the current scope.</param>
/// <param name="pageName">The name of the action method.</param> /// <param name="pageName">The name of the page.</param>
/// <param name="pageHandler">The page handler to generate a form for.</param>
/// <param name="routeValues"> /// <param name="routeValues">
/// An <see cref="object"/> that contains the parameters for a route. The parameters are retrieved through /// An <see cref="object"/> that contains the parameters for a route. The parameters are retrieved through
/// reflection by examining the properties of the <see cref="object"/>. This <see cref="object"/> is typically /// reflection by examining the properties of the <see cref="object"/>. This <see cref="object"/> is typically
@ -180,6 +183,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
TagBuilder GeneratePageForm( TagBuilder GeneratePageForm(
ViewContext viewContext, ViewContext viewContext,
string pageName, string pageName,
string pageHandler,
object routeValues, object routeValues,
string fragment, string fragment,
string method, string method,

View File

@ -1014,7 +1014,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
var pageName = "CustomRouteName"; var pageName = "CustomRouteName";
// Act // Act
var resultPermanent = pageModel.RedirectToPagePreserveMethod(pageName, routeValues); var resultPermanent = pageModel.RedirectToPagePreserveMethod(pageName, routeValues: routeValues);
// Assert // Assert
Assert.IsType<RedirectToPageResult>(resultPermanent); Assert.IsType<RedirectToPageResult>(resultPermanent);
@ -1035,7 +1035,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
var routeName = "CustomRouteName"; var routeName = "CustomRouteName";
// Act // Act
var resultPermanent = pageModel.RedirectToPagePermanentPreserveMethod(routeName, routeValues); var resultPermanent = pageModel.RedirectToPagePermanentPreserveMethod(routeName, routeValues: routeValues);
// Assert // Assert
Assert.IsType<RedirectToPageResult>(resultPermanent); Assert.IsType<RedirectToPageResult>(resultPermanent);

View File

@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Mvc
new ActionDescriptor()); new ActionDescriptor());
var urlHelper = GetUrlHelper(actionContext, expectedUrl); var urlHelper = GetUrlHelper(actionContext, expectedUrl);
var result = new RedirectToPageResult("/MyPage", new { id = 10, test = "value" }, permanentRedirect) var result = new RedirectToPageResult("/MyPage", null, new { id = 10, test = "value" }, permanentRedirect)
{ {
UrlHelper = urlHelper, UrlHelper = urlHelper,
}; };
@ -99,7 +99,7 @@ namespace Microsoft.AspNetCore.Mvc
.Callback((UrlRouteContext c) => context = c) .Callback((UrlRouteContext c) => context = c)
.Returns("some-value"); .Returns("some-value");
var values = new { test = "test-value" }; var values = new { test = "test-value" };
var result = new RedirectToPageResult("/MyPage", values, true, "test-fragment") var result = new RedirectToPageResult("/MyPage", "page-handler", values, true, "test-fragment")
{ {
UrlHelper = urlHelper.Object, UrlHelper = urlHelper.Object,
Protocol = "ftp", Protocol = "ftp",
@ -121,6 +121,11 @@ namespace Microsoft.AspNetCore.Mvc
{ {
Assert.Equal("page", value.Key); Assert.Equal("page", value.Key);
Assert.Equal("/MyPage", value.Value); Assert.Equal("/MyPage", value.Value);
},
value =>
{
Assert.Equal("handler", value.Key);
Assert.Equal("page-handler", value.Value);
}); });
Assert.Equal("ftp", context.Protocol); Assert.Equal("ftp", context.Protocol);
Assert.Equal("test-fragment", context.Fragment); Assert.Equal("test-fragment", context.Fragment);

View File

@ -1132,7 +1132,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing
.Callback((UrlRouteContext context) => actual = context); .Callback((UrlRouteContext context) => actual = context);
// Act // Act
urlHelper.Object.Page("/TestPage", new { id = 13 }, "https"); urlHelper.Object.Page("/TestPage", pageHandler: null, values: new { id = 13 }, protocol: "https");
// Assert // Assert
urlHelper.Verify(); urlHelper.Verify();
@ -1164,7 +1164,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing
.Callback((UrlRouteContext context) => actual = context); .Callback((UrlRouteContext context) => actual = context);
// Act // Act
urlHelper.Object.Page("/TestPage", new { id = 13 }, "https", "mytesthost"); urlHelper.Object.Page("/TestPage", pageHandler: null, values: new { id = 13 }, protocol: "https", host: "mytesthost");
// Assert // Assert
urlHelper.Verify(); urlHelper.Verify();
@ -1196,7 +1196,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing
.Callback((UrlRouteContext context) => actual = context); .Callback((UrlRouteContext context) => actual = context);
// Act // Act
urlHelper.Object.Page("/TestPage", new { id = 13 }, "https", "mytesthost", "#toc"); urlHelper.Object.Page("/TestPage", "test-handler", new { id = 13 }, "https", "mytesthost", "#toc");
// Assert // Assert
urlHelper.Verify(); urlHelper.Verify();
@ -1212,6 +1212,11 @@ namespace Microsoft.AspNetCore.Mvc.Routing
{ {
Assert.Equal("page", value.Key); Assert.Equal("page", value.Key);
Assert.Equal("/TestPage", value.Value); Assert.Equal("/TestPage", value.Value);
},
value =>
{
Assert.Equal("handler", value.Key);
Assert.Equal("test-handler", value.Value);
}); });
Assert.Equal("https", actual.Protocol); Assert.Equal("https", actual.Protocol);
Assert.Equal("mytesthost", actual.Host); Assert.Equal("mytesthost", actual.Host);
@ -1241,7 +1246,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing
// Act // Act
string page = null; string page = null;
urlHelper.Object.Page(page, new { id = 13 }, "https", "mytesthost", "#toc"); urlHelper.Object.Page(page, new { id = 13 });
// Assert // Assert
urlHelper.Verify(); urlHelper.Verify();
@ -1258,9 +1263,6 @@ namespace Microsoft.AspNetCore.Mvc.Routing
Assert.Equal("page", value.Key); Assert.Equal("page", value.Key);
Assert.Equal("ambient-page", value.Value); Assert.Equal("ambient-page", value.Value);
}); });
Assert.Equal("https", actual.Protocol);
Assert.Equal("mytesthost", actual.Host);
Assert.Equal("#toc", actual.Fragment);
} }
[Fact] [Fact]
@ -1287,7 +1289,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing
// Act // Act
string page = null; string page = null;
urlHelper.Object.Page(page, new { id = 13 }, "https", "mytesthost", "#toc"); urlHelper.Object.Page(page, new { id = 13 });
// Assert // Assert
urlHelper.Verify(); urlHelper.Verify();
@ -1335,7 +1337,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing
// Act // Act
string page = null; string page = null;
urlHelper.Object.Page(page, new { handler = "exact-handler" }, "https", "mytesthost", "#toc"); urlHelper.Object.Page(page, "exact-handler", new { handler = "route-value-handler" });
// Assert // Assert
urlHelper.Verify(); urlHelper.Verify();
@ -1354,6 +1356,49 @@ namespace Microsoft.AspNetCore.Mvc.Routing
}); });
} }
[Fact]
public void Page_UsesValueFromRouteValueIfPageHandlerIsNotExplicitySpecified()
{
// Arrange
UrlRouteContext actual = null;
var routeData = new RouteData
{
Values =
{
{ "page", "ambient-page" },
{ "handler", "ambient-handler" },
}
};
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, pageHandler: null, values: new { handler = "route-value-handler" });
// Assert
urlHelper.Verify();
Assert.NotNull(actual);
Assert.Null(actual.RouteName);
Assert.Collection(Assert.IsType<RouteValueDictionary>(actual.Values),
value =>
{
Assert.Equal("handler", value.Key);
Assert.Equal("route-value-handler", value.Value);
},
value =>
{
Assert.Equal("page", value.Key);
Assert.Equal("ambient-page", value.Value);
});
}
[Theory] [Theory]
[InlineData("Sibling", "/Dir1/Dir2/Sibling")] [InlineData("Sibling", "/Dir1/Dir2/Sibling")]
[InlineData("Dir3/Sibling", "/Dir1/Dir2/Dir3/Sibling")] [InlineData("Dir3/Sibling", "/Dir1/Dir2/Dir3/Sibling")]

View File

@ -160,13 +160,15 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
public async Task FormTagHelper_WithPage_AllowsPostingToAnotherPage() public async Task FormTagHelper_WithPage_AllowsPostingToAnotherPage()
{ {
//Arrange //Arrange
var expected = "<form method=\"POST\" action=\"/TagHelper/SelfPost/10\">"; var expected =
@"<form method=""POST"" action=""/TagHelper/SelfPost/10""></form>
<form method=""POST"" action=""/TagHelper/PostWithHandler/Delete/10""></form>";
// Act // Act
var response = await Client.GetStringAsync("/TagHelper/CrossPost"); var response = await Client.GetStringAsync("/TagHelper/CrossPost");
// Assert // Assert
Assert.Contains(expected, response.Trim()); Assert.Equal(expected, response.Trim());
} }
[Fact] [Fact]
@ -176,7 +178,10 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
var expected = var expected =
@"<button formaction=""/TagHelper/CrossPost/10"" /> @"<button formaction=""/TagHelper/CrossPost/10"" />
<input type=""submit"" formaction=""/TagHelper/CrossPost/10"" /> <input type=""submit"" formaction=""/TagHelper/CrossPost/10"" />
<input type=""image"" formaction=""/TagHelper/CrossPost/10"" />"; <input type=""image"" formaction=""/TagHelper/CrossPost/10"" />
<button formaction=""/TagHelper/PostWithHandler/Edit/11"" />
<input type=""submit"" formaction=""/TagHelper/PostWithHandler/Edit/11"" />
<input type=""image"" formaction=""/TagHelper/PostWithHandler/Delete/11"" />";
// Act // Act
var response = await Client.GetStringAsync("/TagHelper/FormAction"); var response = await Client.GetStringAsync("/TagHelper/FormAction");

View File

@ -965,7 +965,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
var pageName = "CustomRouteName"; var pageName = "CustomRouteName";
// Act // Act
var resultPermanent = pageModel.RedirectToPagePreserveMethod(pageName, routeValues); var resultPermanent = pageModel.RedirectToPagePreserveMethod(pageName, routeValues: routeValues);
// Assert // Assert
Assert.IsType<RedirectToPageResult>(resultPermanent); Assert.IsType<RedirectToPageResult>(resultPermanent);
@ -986,7 +986,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
var routeName = "CustomRouteName"; var routeName = "CustomRouteName";
// Act // Act
var resultPermanent = pageModel.RedirectToPagePermanentPreserveMethod(routeName, routeValues); var resultPermanent = pageModel.RedirectToPagePermanentPreserveMethod(routeName, routeValues: routeValues);
// Assert // Assert
Assert.IsType<RedirectToPageResult>(resultPermanent); Assert.IsType<RedirectToPageResult>(resultPermanent);

View File

@ -1042,7 +1042,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
var pageName = "CustomRouteName"; var pageName = "CustomRouteName";
// Act // Act
var resultPermanent = pageModel.RedirectToPagePreserveMethod(pageName, routeValues); var resultPermanent = pageModel.RedirectToPagePreserveMethod(pageName, routeValues: routeValues);
// Assert // Assert
Assert.IsType<RedirectToPageResult>(resultPermanent); Assert.IsType<RedirectToPageResult>(resultPermanent);
@ -1063,7 +1063,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
var routeName = "CustomRouteName"; var routeName = "CustomRouteName";
// Act // Act
var resultPermanent = pageModel.RedirectToPagePermanentPreserveMethod(routeName, routeValues); var resultPermanent = pageModel.RedirectToPagePermanentPreserveMethod(routeName, routeValues: routeValues);
// Assert // Assert
Assert.IsType<RedirectToPageResult>(resultPermanent); Assert.IsType<RedirectToPageResult>(resultPermanent);

View File

@ -393,6 +393,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
It.IsAny<ViewContext>(), It.IsAny<ViewContext>(),
string.Empty, string.Empty,
"/User/Home/Index", "/User/Home/Index",
"page-handler",
"http", "http",
"contoso.com", "contoso.com",
"hello=world", "hello=world",
@ -403,6 +404,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
var anchorTagHelper = new AnchorTagHelper(generator.Object) var anchorTagHelper = new AnchorTagHelper(generator.Object)
{ {
Page = "/User/Home/Index", Page = "/User/Home/Index",
PageHandler = "page-handler",
Fragment = "hello=world", Fragment = "hello=world",
Host = "contoso.com", Host = "contoso.com",
Protocol = "http", Protocol = "http",
@ -424,6 +426,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[InlineData("Fragment")] [InlineData("Fragment")]
[InlineData("asp-route-")] [InlineData("asp-route-")]
[InlineData("Page")] [InlineData("Page")]
[InlineData("PageHandler")]
public async Task ProcessAsync_ThrowsIfHrefConflictsWithBoundAttributes(string propertyName) public async Task ProcessAsync_ThrowsIfHrefConflictsWithBoundAttributes(string propertyName)
{ {
// Arrange // Arrange
@ -451,7 +454,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
var expectedErrorMessage = "Cannot override the 'href' attribute for <a>. An <a> with a specified " + var expectedErrorMessage = "Cannot override the 'href' attribute for <a>. An <a> with a specified " +
"'href' must not have attributes starting with 'asp-route-' or an " + "'href' must not have attributes starting with 'asp-route-' or an " +
"'asp-action', 'asp-controller', 'asp-area', 'asp-route', 'asp-protocol', 'asp-host', " + "'asp-action', 'asp-controller', 'asp-area', 'asp-route', 'asp-protocol', 'asp-host', " +
"'asp-fragment', or 'asp-page' attribute."; "'asp-fragment', 'asp-page' or 'asp-page-handler' attribute.";
var context = new TagHelperContext( var context = new TagHelperContext(
tagName: "test", tagName: "test",
@ -491,7 +494,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
"Cannot determine the 'href' attribute for <a>. The following attributes are mutually exclusive:", "Cannot determine the 'href' attribute for <a>. The following attributes are mutually exclusive:",
"asp-route", "asp-route",
"asp-controller, asp-action", "asp-controller, asp-action",
"asp-page"); "asp-page, asp-page-handler");
var context = new TagHelperContext( var context = new TagHelperContext(
tagName: "test", tagName: "test",
@ -529,7 +532,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
"Cannot determine the 'href' attribute for <a>. The following attributes are mutually exclusive:", "Cannot determine the 'href' attribute for <a>. The following attributes are mutually exclusive:",
"asp-route", "asp-route",
"asp-controller, asp-action", "asp-controller, asp-action",
"asp-page"); "asp-page, asp-page-handler");
var context = new TagHelperContext( var context = new TagHelperContext(
tagName: "test", tagName: "test",
@ -567,7 +570,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
"Cannot determine the 'href' attribute for <a>. The following attributes are mutually exclusive:", "Cannot determine the 'href' attribute for <a>. The following attributes are mutually exclusive:",
"asp-route", "asp-route",
"asp-controller, asp-action", "asp-controller, asp-action",
"asp-page"); "asp-page, asp-page-handler");
var context = new TagHelperContext( var context = new TagHelperContext(
tagName: "test", tagName: "test",

View File

@ -475,7 +475,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
var expectedErrorMessage = $"Cannot override the 'formaction' attribute for <{tagName}>. <{tagName}> " + var expectedErrorMessage = $"Cannot override the 'formaction' attribute for <{tagName}>. <{tagName}> " +
"elements with a specified 'formaction' must not have attributes starting with 'asp-route-' or an " + "elements with a specified 'formaction' must not have attributes starting with 'asp-route-' or an " +
"'asp-action', 'asp-controller', 'asp-area', 'asp-fragment', or 'asp-route' attribute."; "'asp-action', 'asp-controller', 'asp-area', 'asp-fragment', 'asp-route', 'asp-page' or 'asp-page-handler' attribute.";
var context = new TagHelperContext( var context = new TagHelperContext(
tagName: "form-action", tagName: "form-action",
@ -515,7 +515,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
$"Cannot determine the 'formaction' attribute for <{tagName}>. The following attributes are mutually exclusive:", $"Cannot determine the 'formaction' attribute for <{tagName}>. The following attributes are mutually exclusive:",
"asp-route", "asp-route",
"asp-controller, asp-action", "asp-controller, asp-action",
"asp-page"); "asp-page, asp-page-handler");
var context = new TagHelperContext( var context = new TagHelperContext(
tagName: "form-action", tagName: "form-action",
@ -553,7 +553,45 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
$"Cannot determine the 'formaction' attribute for <{tagName}>. The following attributes are mutually exclusive:", $"Cannot determine the 'formaction' attribute for <{tagName}>. The following attributes are mutually exclusive:",
"asp-route", "asp-route",
"asp-controller, asp-action", "asp-controller, asp-action",
"asp-page"); "asp-page, asp-page-handler");
var context = new TagHelperContext(
tagName: "form-action",
allAttributes: new TagHelperAttributeList(
Enumerable.Empty<TagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test");
// Act & Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => tagHelper.ProcessAsync(context, output));
Assert.Equal(expectedErrorMessage, ex.Message);
}
[Theory]
[InlineData("button")]
[InlineData("submit")]
public async Task ProcessAsync_ThrowsIfRouteAndPageHandlerProvided(string tagName)
{
// Arrange
var urlHelperFactory = new Mock<IUrlHelperFactory>().Object;
var tagHelper = new FormActionTagHelper(urlHelperFactory)
{
Route = "Default",
PageHandler = "PageHandler",
};
var output = new TagHelperOutput(
tagName,
attributes: new TagHelperAttributeList(),
getChildContentAsync: (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(null));
var expectedErrorMessage = string.Join(
Environment.NewLine,
$"Cannot determine the 'formaction' attribute for <{tagName}>. The following attributes are mutually exclusive:",
"asp-route",
"asp-controller, asp-action",
"asp-page, asp-page-handler");
var context = new TagHelperContext( var context = new TagHelperContext(
tagName: "form-action", tagName: "form-action",
@ -591,7 +629,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
$"Cannot determine the 'formaction' attribute for <{tagName}>. The following attributes are mutually exclusive:", $"Cannot determine the 'formaction' attribute for <{tagName}>. The following attributes are mutually exclusive:",
"asp-route", "asp-route",
"asp-controller, asp-action", "asp-controller, asp-action",
"asp-page"); "asp-page, asp-page-handler");
var context = new TagHelperContext( var context = new TagHelperContext(
tagName: "form-action", tagName: "form-action",

View File

@ -775,6 +775,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
.Setup(mock => mock.GeneratePageForm( .Setup(mock => mock.GeneratePageForm(
viewContext, viewContext,
"/Home/Admin/Post", "/Home/Admin/Post",
"page-handler",
null, null,
"hello-world", "hello-world",
null, null,
@ -786,6 +787,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
Antiforgery = false, Antiforgery = false,
ViewContext = viewContext, ViewContext = viewContext,
Page = "/Home/Admin/Post", Page = "/Home/Admin/Post",
PageHandler = "page-handler",
Fragment = "hello-world", Fragment = "hello-world",
}; };
@ -851,6 +853,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[InlineData("Action")] [InlineData("Action")]
[InlineData("Controller")] [InlineData("Controller")]
[InlineData("Page")] [InlineData("Page")]
[InlineData("PageHandler")]
[InlineData("asp-route-")] [InlineData("asp-route-")]
public async Task ProcessAsync_ThrowsIfActionConflictsWithBoundAttributes(string propertyName) public async Task ProcessAsync_ThrowsIfActionConflictsWithBoundAttributes(string propertyName)
{ {
@ -874,7 +877,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
var expectedErrorMessage = "Cannot override the 'action' attribute for <form>. A <form> with a specified " + var expectedErrorMessage = "Cannot override the 'action' attribute for <form>. A <form> with a specified " +
"'action' must not have attributes starting with 'asp-route-' or an " + "'action' must not have attributes starting with 'asp-route-' or an " +
"'asp-action', 'asp-controller', 'asp-fragment', 'asp-area', 'asp-route' or 'asp-page' attribute."; "'asp-action', 'asp-controller', 'asp-fragment', 'asp-area', 'asp-route', 'asp-page' or 'asp-page-handler' attribute.";
var context = new TagHelperContext( var context = new TagHelperContext(
tagName: "form", tagName: "form",

View File

@ -1,5 +1,4 @@
@page "{id:int?}" @page "{id:int?}"
<form method="POST" asp-page="/TagHelper/SelfPost" asp-route-id="10"> <form method="POST" asp-page="/TagHelper/SelfPost" asp-route-id="10" asp-antiforgery="false"></form>
<input type="submit" value="Submit" /> <form method="POST" asp-page="PostWithHandler" asp-page-handler="Delete" asp-route-id="10" asp-antiforgery="false"></form>
</form>

View File

@ -1,4 +1,7 @@
@page @page
<button asp-page="/TagHelper/CrossPost" asp-route-id="10" /> <button asp-page="/TagHelper/CrossPost" asp-route-id="10" />
<input type="submit" asp-page="/TagHelper/CrossPost" asp-route-id="10" /> <input type="submit" asp-page="/TagHelper/CrossPost" asp-route-id="10" />
<input type="image" asp-page="/TagHelper/CrossPost" asp-route-id="10" /> <input type="image" asp-page="/TagHelper/CrossPost" asp-route-id="10" />
<button asp-page="PostWithHandler" asp-page-handler="Edit" asp-route-id="11" />
<input type="submit" asp-page="PostWithHandler" asp-page-handler="Edit" asp-route-id="11" />
<input type="image" asp-page="PostWithHandler" asp-page-handler="Delete" asp-route-id="11" />

View File

@ -0,0 +1,16 @@
@page "{handler?}/{id?}"
@function
{
public IActionResult OnPostEdit(int id)
{
return View();
}
public IActionResult OnPostDelete(int id)
{
return View();
}
}
<form method="post" asp-page-handler="Edit" asp-route-id="10" asp-antiforgery="false"></form>