// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc.Core;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Routing;
namespace Microsoft.AspNetCore.Mvc
{
public static class UrlHelperExtensions
{
///
/// Generates a URL with an absolute path for an action method.
///
/// The .
/// The generated URL.
public static string Action(this IUrlHelper helper)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.Action(
action: null,
controller: null,
values: null,
protocol: null,
host: null,
fragment: null);
}
///
/// Generates a URL with an absolute path for an action method, which contains the specified
/// name.
///
/// The .
/// The name of the action method.
/// The generated URL.
public static string Action(this IUrlHelper helper, string action)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.Action(action, controller: null, values: null, protocol: null, host: null, fragment: null);
}
///
/// Generates a URL with an absolute path for an action method, which contains the specified
/// name and route .
///
/// The .
/// The name of the action method.
/// An object that contains route values.
/// The generated URL.
public static string Action(this IUrlHelper helper, string action, object values)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.Action(action, controller: null, values: values, protocol: null, host: null, fragment: null);
}
///
/// Generates a URL with an absolute path for an action method, which contains the specified
/// and names.
///
/// The .
/// The name of the action method.
/// The name of the controller.
/// The generated URL.
public static string Action(this IUrlHelper helper, string action, string controller)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.Action(action, controller, values: null, protocol: null, host: null, fragment: null);
}
///
/// Generates a URL with an absolute path for an action method, which contains the specified
/// name, name, and route .
///
/// The .
/// The name of the action method.
/// The name of the controller.
/// An object that contains route values.
/// The generated URL.
public static string Action(this IUrlHelper helper, string action, string controller, object values)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.Action(action, controller, values, protocol: null, host: null, fragment: null);
}
///
/// Generates a URL with an absolute path for an action method, which contains the specified
/// name, name, route , and
/// to use.
///
/// The .
/// The name of the action method.
/// The name of the controller.
/// An object that contains route values.
/// The protocol for the URL, such as "http" or "https".
/// The generated URL.
public static string Action(
this IUrlHelper helper,
string action,
string controller,
object values,
string protocol)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.Action(action, controller, values, protocol, host: null, fragment: null);
}
///
/// Generates a URL with an absolute path for an action method, which contains the specified
/// name, name, route ,
/// to use, and name.
/// Generates an absolute URL if the and are
/// non-null.
///
/// The .
/// The name of the action method.
/// The name of the controller.
/// An object that contains route values.
/// The protocol for the URL, such as "http" or "https".
/// The host name for the URL.
/// The generated URL.
public static string Action(
this IUrlHelper helper,
string action,
string controller,
object values,
string protocol,
string host)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.Action(action, controller, values, protocol, host, fragment: null);
}
///
/// Generates a URL with an absolute path for an action method, which contains the specified
/// name, name, route ,
/// to use, name, and .
/// Generates an absolute URL if the and are
/// non-null.
///
/// The .
/// The name of the action method.
/// The name of the controller.
/// An object that contains route values.
/// The protocol for the URL, such as "http" or "https".
/// The host name for the URL.
/// The fragment for the URL.
/// The generated URL.
public static string Action(
this IUrlHelper helper,
string action,
string controller,
object values,
string protocol,
string host,
string fragment)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.Action(new UrlActionContext()
{
Action = action,
Controller = controller,
Host = host,
Values = values,
Protocol = protocol,
Fragment = fragment
});
}
///
/// Generates a URL with an absolute path for the specified route .
///
/// The .
/// An object that contains route values.
/// The generated URL.
public static string RouteUrl(this IUrlHelper helper, object values)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.RouteUrl(routeName: null, values: values, protocol: null, host: null, fragment: null);
}
///
/// Generates a URL with an absolute path for the specified .
///
/// The .
/// The name of the route that is used to generate URL.
/// The generated URL.
public static string RouteUrl(this IUrlHelper helper, string routeName)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.RouteUrl(routeName, values: null, protocol: null, host: null, fragment: null);
}
///
/// Generates a URL with an absolute path for the specified and route
/// .
///
/// The .
/// The name of the route that is used to generate URL.
/// An object that contains route values.
/// The generated URL.
public static string RouteUrl(this IUrlHelper helper, string routeName, object values)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.RouteUrl(routeName, values, protocol: null, host: null, fragment: null);
}
///
/// Generates a URL with an absolute path for the specified route and route
/// , which contains the specified to use.
///
/// The .
/// The name of the route that is used to generate URL.
/// An object that contains route values.
/// The protocol for the URL, such as "http" or "https".
/// The generated URL.
public static string RouteUrl(
this IUrlHelper helper,
string routeName,
object values,
string protocol)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.RouteUrl(routeName, values, protocol, host: null, fragment: null);
}
///
/// Generates a URL with an absolute path for the specified route and route
/// , which contains the specified to use and
/// name. Generates an absolute URL if
/// and are non-null.
///
/// The .
/// The name of the route that is used to generate URL.
/// An object that contains route values.
/// The protocol for the URL, such as "http" or "https".
/// The host name for the URL.
/// The generated URL.
public static string RouteUrl(
this IUrlHelper helper,
string routeName,
object values,
string protocol,
string host)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.RouteUrl(routeName, values, protocol, host, fragment: null);
}
///
/// Generates a URL with an absolute path for the specified route and route
/// , which contains the specified to use,
/// name and . Generates an absolute URL if
/// and are non-null.
///
/// The .
/// The name of the route that is used to generate URL.
/// An object that contains route values.
/// The protocol for the URL, such as "http" or "https".
/// The host name for the URL.
/// The fragment for the URL.
/// The generated URL.
public static string RouteUrl(
this IUrlHelper helper,
string routeName,
object values,
string protocol,
string host,
string fragment)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.RouteUrl(new UrlRouteContext()
{
RouteName = routeName,
Values = values,
Protocol = protocol,
Host = host,
Fragment = fragment
});
}
///
/// Generates a URL with an absolute path for the specified .
///
/// The .
/// The page name to generate the url for.
/// The generated URL.
public static string Page(this IUrlHelper urlHelper, string pageName)
=> Page(urlHelper, pageName, values: null);
///
/// Generates a URL with an absolute path for the specified .
///
/// The .
/// The page name to generate the url for.
/// The handler to generate the url for.
/// The generated URL.
public static string Page(this IUrlHelper urlHelper, string pageName, string pageHandler)
=> Page(urlHelper, pageName, pageHandler, values: null);
///
/// Generates a URL with an absolute path for the specified .
///
/// The .
/// The page name to generate the url for.
/// An object that contains route values.
/// The generated URL.
public static string Page(this IUrlHelper urlHelper, string pageName, object values)
=> Page(urlHelper, pageName, pageHandler: null, values: values);
///
/// Generates a URL with an absolute path for the specified .
///
/// The .
/// The page name to generate the url for.
/// The handler to generate the url for.
/// An object that contains route values.
/// The generated URL.
public static string Page(
this IUrlHelper urlHelper,
string pageName,
string pageHandler,
object values)
=> Page(urlHelper, pageName, pageHandler, values, protocol: null);
///
/// Generates a URL with an absolute path for the specified .
///
/// The .
/// The page name to generate the url for.
/// The handler to generate the url for.
/// An object that contains route values.
/// The protocol for the URL, such as "http" or "https".
/// The generated URL.
public static string Page(
this IUrlHelper urlHelper,
string pageName,
string pageHandler,
object values,
string protocol)
=> Page(urlHelper, pageName, pageHandler, values, protocol, host: null, fragment: null);
///
/// Generates a URL with an absolute path for the specified .
///
/// The .
/// The page name to generate the url for.
/// The handler to generate the url for.
/// An object that contains route values.
/// The protocol for the URL, such as "http" or "https".
/// The host name for the URL.
/// The generated URL.
public static string Page(
this IUrlHelper urlHelper,
string pageName,
string pageHandler,
object values,
string protocol,
string host)
=> Page(urlHelper, pageName, pageHandler, values, protocol, host, fragment: null);
///
/// Generates a URL with an absolute path for the specified .
///
/// The .
/// The page name to generate the url for.
/// The handler to generate the url for.
/// An object that contains route values.
/// The protocol for the URL, such as "http" or "https".
/// The host name for the URL.
/// The fragment for the URL.
/// The generated URL.
public static string Page(
this IUrlHelper urlHelper,
string pageName,
string pageHandler,
object values,
string protocol,
string host,
string fragment)
{
if (urlHelper == null)
{
throw new ArgumentNullException(nameof(urlHelper));
}
var routeValues = new RouteValueDictionary(values);
var ambientValues = urlHelper.ActionContext.RouteData.Values;
if (string.IsNullOrEmpty(pageName))
{
if (!routeValues.ContainsKey("page") &&
ambientValues.TryGetValue("page", out var value))
{
routeValues["page"] = value;
}
}
else
{
routeValues["page"] = CalculatePageName(urlHelper.ActionContext, pageName);
}
if (string.IsNullOrEmpty(pageHandler))
{
if (!routeValues.ContainsKey("handler") &&
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(
routeName: null,
values: routeValues,
protocol: protocol,
host: host,
fragment: fragment);
}
private static object CalculatePageName(ActionContext actionContext, string pageName)
{
Debug.Assert(pageName.Length > 0);
// Paths not qualified with a leading slash are treated as relative to the current page.
if (pageName[0] != '/')
{
var currentPagePath = NormalizedRouteValue.GetNormalizedRouteValue(actionContext, "page");
if (string.IsNullOrEmpty(currentPagePath))
{
// Disallow the use sibling page routing, a Razor page specific feature, from a non-page action.
throw new InvalidOperationException(Resources.FormatUrlHelper_RelativePagePathIsNotSupported(pageName));
}
return ViewEnginePath.CombinePath(currentPagePath, pageName);
}
return pageName;
}
}
}