Как найти абсолютный URL-адрес действия в ASP.NET MVC?

239

Мне нужно сделать что-то вроде этого:

<script type="text/javascript">
    token_url = "http://example.com/your_token_url";
</script>

Я использую бета-версию MVC, но я не могу понять, как получить абсолютный URL-адрес действия. Я хотел бы сделать что-то вроде этого:

<%= Url.AbsoluteAction("Action","Controller")) %>

Есть ли для этого вспомогательный метод или метод Page?

Майк Комсток
источник

Ответы:

480

Нажмите здесь для получения дополнительной информации, но по существу нет необходимости в методах расширения. Он уже запечен, но не очень интуитивно.

Url.Action("Action", null, null, Request.Url.Scheme);
Адам Боддингтон
источник
6
Интересно, что если вы укажете протокол, URL будет абсолютным
Casebash
24
Этот ответ является лучшим, так что Resharper все еще может проверить, что существует Action и Controller. Я бы предложил использовать Request.Url.Scheme вместо http, чтобы оба варианта поддерживали http и https.
Пбиркофф
2
@Pbirkoff, согласитесь, это лучший ответ, но вы можете знать, что вы можете аннотировать свои собственные методы, чтобы ReSharper знал, что параметры представляют действия / контроллеры. Таким образом, R # может по-прежнему проверять предоставленные вами строки, как это хорошо.
Дрю Ноакс
3
Небольшое улучшение может заключаться в замене «http» на то, Request.Url.Schemeчтобы при использовании HTTPS сгенерированный URL-адрес также использовал HTTPS.
Эрик Ширбум
1
Это также работает Html.ActionLink(любой из методов, которые принимают протокол, например, последние 2 в MVC 4)
Крис
74

Расширить UrlHelper

namespace System.Web.Mvc
{
    public static class HtmlExtensions
    {
        public static string AbsoluteAction(this UrlHelper url, string action, string controller)
        {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;

            string absoluteAction = string.Format(
                "{0}://{1}{2}",
                requestUrl.Scheme,
                requestUrl.Authority,
                url.Action(action, controller));

            return absoluteAction;
        }
    }
}

Тогда назови это так

<%= Url.AbsoluteAction("Dashboard", "Account")%>

РЕДАКТИРОВАТЬ - РЕШАРПЕР АННОТАЦИИ

Самый одобренный комментарий к принятому ответу: This answer is the better one, this way Resharper can still validate that the Action and Controller exists.так вот пример, как вы могли бы получить такое же поведение.

using JetBrains.Annotations

namespace System.Web.Mvc
{
    public static class HtmlExtensions
    {
        public static string AbsoluteAction(
            this UrlHelper url,
            [AspMvcAction]
            string action,
            [AspMvcController]
            string controller)
        {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;

            string absoluteAction = string.Format(
                "{0}://{1}{2}",
                requestUrl.Scheme,
                requestUrl.Authority,
                url.Action(action, controller));

            return absoluteAction;
        }
    }
}

Вспомогательная информация:

Charlino
источник
3
Я бы добавил также необязательные параметры для этого решения. Это должно охватывать все случаи.
Евгений Торика
Очень хорошо! Я использовал этот код, но я сделал единственный аргументlativeUrl, чтобы вызывающая сторона могла создать его, используя любой метод Url, который им нравится (значения маршрутизатора и т. Д.), И ваш метод может быть просто ответственным за то, чтобы сделать его относительным. Так что мое: AbsoluteUrl (это URL UrlHelper, строкаlativeUrl).
Роб Кент
26
<%= Url.Action("About", "Home", null, Request.Url.Scheme) %>
<%= Url.RouteUrl("Default", new { Action = "About" }, Request.Url.Scheme) %>
Райан Сэмпсон
источник
21

Используя ответ @Charlino в качестве руководства, я придумал это.

Документация ASP.NET MVC для UrlHelper показывает, что Url.Action будет возвращать полный URL- адрес, если передано имя хоста и протокол. Я создал эти помощники для принудительного предоставления имени хоста и протокола. Многократные перегрузки отражают перегрузки для Url.Action:

using System.Web.Routing;

namespace System.Web.Mvc {
    public static class HtmlExtensions {

        public static string AbsoluteAction(this UrlHelper url, string actionName) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, null, (RouteValueDictionary)null, 
                              requestUrl.Scheme, null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            object routeValues) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, null, new RouteValueDictionary(routeValues), 
                              requestUrl.Scheme, null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            RouteValueDictionary routeValues) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, null, routeValues, requestUrl.Scheme, null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            string controllerName) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, controllerName, (RouteValueDictionary)null, 
                              requestUrl.Scheme, null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            string controllerName, 
                                            object routeValues) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, controllerName, 
                              new RouteValueDictionary(routeValues), requestUrl.Scheme, 
                              null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            string controllerName, 
                                            RouteValueDictionary routeValues) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, controllerName, routeValues, requestUrl.Scheme, 
                              null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            string controllerName, object routeValues, 
                                            string protocol) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, controllerName, 
                              new RouteValueDictionary(routeValues), protocol, null);
        }

    }
}
Роли Бакнер
источник
4
Спасибо за код, мне очень помогли, но есть проблема с этим решением, которая обычно возникает в процессе разработки. Если сайт размещен на определенном порту, информация о порте включается в requestUrl.Authority , например localhost: 4423 . По какой-то причине метод Action снова добавляет порт. Так что либо это ошибка внутри метода действия, либо вы не должны указывать здесь порт. Но какой из доступных свойств по запросу является правильным (DnsSafeHost или Host)? Ну, решение довольно простое: просто укажите null, и метод Action заполнит правильное значение.
ntziolis
Я обновил ответ, чтобы включить предложение @ ntziolis.
Эндрю Арнотт
3

Я не уверен, есть ли встроенный способ сделать это, но вы можете свернуть свой собственный метод HtmlHelper.

Что-то вроде следующего

namespace System.Web.Mvc
{
    public static class HtmlExtensions
    {
        public static string AbsoluteAction(this HtmlHelper html, string actionUrl)
        {
            Uri requestUrl = html.ViewContext.HttpContext.Request.Url;

            string absoluteAction = string.Format("{0}://{1}{2}",
                                                  requestUrl.Scheme,
                                                  requestUrl.Authority,
                                                  actionUrl);

            return absoluteAction;
        }
    }
}

Тогда назови это так

<%= Html.AbsoluteAction(Url.Action("Dashboard", "Account"))%> »

HTHs, Чарльз

Charlino
источник
2

Полный ответ с аргументами будет:

var url = Url.Action("ActionName", "ControllerName", new { id = "arg_value" }, Request.Url.Scheme);

и это даст абсолютный URL

Dashrath
источник
1

Тот же результат, но немного чище (без объединения / форматирования строк):

public static Uri GetBaseUrl(this UrlHelper url)
{
    Uri contextUri = new Uri(url.RequestContext.HttpContext.Request.Url, url.RequestContext.HttpContext.Request.RawUrl);
    UriBuilder realmUri = new UriBuilder(contextUri) { Path = url.RequestContext.HttpContext.Request.ApplicationPath, Query = null, Fragment = null };
    return realmUri.Uri;
}

public static string ActionAbsolute(this UrlHelper url, string actionName, string controllerName)
{
    return new Uri(GetBaseUrl(url), url.Action(actionName, controllerName)).AbsoluteUri;
}
veggerby
источник
0

Может быть, это (?):

<%= 
  Request.Url.GetLeftPart(UriPartial.Authority) + 
  Url.Action("Action1", "Controller2", new {param1="bla", param2="blabla" })
%>
tytusse
источник
0

env: ядро ​​dotnet версии 1.0.4

Url.Action("Join",null, null,Context.Request.IsHttps?"https":"http");
guhyeon
источник