Получение полного URL-адреса действия в ASP.NET MVC
Есть ли встроенный способ получения полного URL-адреса действия?
Я ищу что-то вроде GetFullUrl("Action", "Controller")
, которое вернет что-то вроде http://www.fred.com/Controller/Action
.
Причина, по которой я ищу это, заключается в том, чтобы избежать URL-адресов жесткого кодирования в автоматических электронных письмах, которые генерируются, чтобы URL-адреса всегда могли быть сгенерированы относительно текущего местоположения сайта.
Ответы
Ответ 1
Существует перегрузка Url.Action, которая принимает ваш желаемый протокол (например, http, https) в качестве аргумента. Если вы укажете это, вы получите полный URL-адрес.
Вот пример, который использует протокол текущего запроса в методе действий:
var fullUrl = this.Url.Action("Edit", "Posts", new { id = 5 }, this.Request.Url.Scheme);
HtmlHelper (@Html) также имеет перегрузку метода ActionLink, который можно использовать в бритве для создания элемента привязки, но для этого также требуются параметры hostName и фрагмента. Поэтому я просто решил снова использовать @Url.Action:
<span>
Copy
<a href='@Url.Action("About", "Home", null, Request.Url.Scheme)'>this link</a>
and post it anywhere on the internet!
</span>
Ответ 2
Как сказал Пэдди: , если вы используете перегрузку UrlHelper.Action()
, которая явно указывает используемый протокол, сгенерированный URL будет абсолютным и полностью квалифицированным, а не относительным.
Я написал сообщение в блоге Как создать URL абсолютного действия с использованием класса UrlHelper, в котором я предлагаю написать собственный метод расширения для ради удобочитаемости:
/// <summary>
/// Generates a fully qualified URL to an action method by using
/// the specified action name, controller name and route values.
/// </summary>
/// <param name="url">The URL helper.</param>
/// <param name="actionName">The name of the action method.</param>
/// <param name="controllerName">The name of the controller.</param>
/// <param name="routeValues">The route values.</param>
/// <returns>The absolute URL.</returns>
public static string AbsoluteAction(this UrlHelper url,
string actionName, string controllerName, object routeValues = null)
{
string scheme = url.RequestContext.HttpContext.Request.Url.Scheme;
return url.Action(actionName, controllerName, routeValues, scheme);
}
Затем вы можете просто использовать его в своем представлении:
@Url.AbsoluteAction("Action", "Controller")
Ответ 3
Это то, что вам нужно сделать.
@Url.Action(action,controller, null, Request.Url.Scheme)
Ответ 4
Этот вопрос специфичен для ASP.NET, однако я уверен, что некоторые из вас принесут пользу системному агностическому javascript, который выгоден во многих ситуациях.
ОБНОВЛЕНИЕ:. Способ получения url, сформированного за пределами самой страницы, хорошо описан в ответах выше.
Или вы можете сделать oneliner следующим образом:
new UrlHelper(actionExecutingContext.RequestContext).Action(
"SessionTimeout", "Home",
new {area = string.Empty},
actionExecutingContext.Request.Url!= null?
actionExecutingContext.Request.Url.Scheme : "http"
);
из фильтра или:
new UrlHelper(this.Request.RequestContext).Action(
"Details",
"Journey",
new { area = productType },
this.Request.Url!= null? this.Request.Url.Scheme : "http"
);
Однако довольно часто нужно получить URL-адрес текущей страницы, для тех случаев, когда используется Html.Action
, и ставить имя и контроллер страницы, в которой вы находитесь, мне неловко. В таких случаях я предпочитаю использовать JavaScript. Это особенно хорошо в системах, которые наполовину переписаны MVT половину веб-форм, половина vb- script половина, которую знает Бог, - и для получения URL-адреса текущей страницы каждый раз нужно использовать разные методы.
Один из способов - использовать JavaScript для получения URL-адреса window.location.href
другой - document.URL
Ответ 5
Это может быть только я, действительно, действительно придирчивый, но мне нравится определять константы только один раз. Если вы используете какой-либо из подходов, определенных выше, ваша константа действия будет определяться несколько раз.
Чтобы этого избежать, вы можете сделать следующее:
public class Url
{
public string LocalUrl { get; }
public Url(string localUrl)
{
LocalUrl = localUrl;
}
public override string ToString()
{
return LocalUrl;
}
}
public abstract class Controller
{
public Url RootAction => new Url(GetUrl());
protected abstract string Root { get; }
public Url BuildAction(string actionName)
{
var localUrl = GetUrl() + "/" + actionName;
return new Url(localUrl);
}
private string GetUrl()
{
if (Root == "")
{
return "";
}
return "/" + Root;
}
public override string ToString()
{
return GetUrl();
}
}
Затем создайте свои контроллеры, например, DataController:
public static readonly DataController Data = new DataController();
public class DataController : Controller
{
public const string DogAction = "dog";
public const string CatAction = "cat";
public const string TurtleAction = "turtle";
protected override string Root => "data";
public Url Dog => BuildAction(DogAction);
public Url Cat => BuildAction(CatAction);
public Url Turtle => BuildAction(TurtleAction);
}
Затем просто используйте его как:
// GET: Data/Cat
[ActionName(ControllerRoutes.DataController.CatAction)]
public ActionResult Etisys()
{
return View();
}
И из вашего .cshtml(или любого кода)
<ul>
<li><a href="@ControllerRoutes.Data.Dog">Dog</a></li>
<li><a href="@ControllerRoutes.Data.Cat">Cat</a></li>
</ul>
Это определенно намного больше работы, но я спокойно понимаю, что проверка времени компиляции на моей стороне.
Ответ 6
У меня возникла проблема с этим, мой сервер работал за балансировщиком нагрузки. Балансировщик нагрузки завершил соединение SSL/TLS. Затем он передал запрос веб-серверам с помощью http.
Используя метод Url.Action() с Request.Url.Schema, он продолжал создавать URL-адрес http, в моем случае для создания ссылки в автоматическом электронном письме (который мне не понравился PenTester).
Возможно, я немного обманул, но это именно то, что мне нужно было для создания https-url:
<a href="@Url.Action("Action", "Controller", new { id = Model.Id }, "https")">Click Here</a>
Я действительно использую AppSetting для web.config, поэтому я могу использовать http при локальном отладке, но во всех средах тестирования и prod используется преобразование для установки значения https.