// 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; } } }