Як знайти абсолютний URL-адресу дії в ASP.NET MVC?


239

Мені потрібно зробити щось подібне:

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

Я використовую бета-версію MVC, але не можу зрозуміти, як отримати абсолютний URL-адресу дії. Я хотів би зробити щось подібне:

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

Чи є для цього помічник чи метод сторінки?

Відповіді:


480

Клацніть тут для отримання додаткової інформації, але по суті, немає необхідності в методах розширення. Це вже запекло, тільки не дуже інтуїтивно.

Url.Action("Action", null, null, Request.Url.Scheme);

6
Цікаво, тому якщо ви вкажете протокол, URL-адреса абсолютна
Casebash

24
Ця відповідь є кращою, тому Resharper все ще може підтвердити, що існує дія та контролер. Я б запропонував використовувати Request.Url.Scheme замість http, таким чином підтримуються і http, і https.
Pbirkoff

2
@Pbirkoff, погоджуйтеся, що це найкраща відповідь, але ви, можливо, хочете знати, що ви можете коментувати свої власні методи для ReSharper, щоб знати, що параметри представляють дії / контролери. Таким чином R # все ще може підтвердити надані вами рядки, як це добре.
Дрю Ноакс

3
Невеликим поліпшенням може стати заміна "http" на Request.Url.Schemeтак, що якщо ви використовуєте HTTPS, створений URL також використовуватиме HTTPS.
Erik Schierboom

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

Інформація про підтримку:


3
Я б додав також необов'язкові параметри для цього рішення. Це має охоплювати всі випадки.
Eugeniu Torica

Дуже хороша! Я використовував цей код, але я створив єдиний аргумент relaUrl, щоб абонент міг створити його, використовуючи будь-який метод URL-адреси, який їм подобається (значення маршрутизатора тощо), і ваш метод може просто нести відповідальність за його відношення. Отже, моя: AbsoluteUrl (ця URL-адреса UrlHelper, рядковий relaUrl).
Роб Кент


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
Thx для коду, мені дуже допомогли, але є проблема з цим рішенням, яке зазвичай виникає під час розробки. Якщо сайт розміщений на певному порту, інформація про порт міститься у 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"))%> »

HTH, Чарльз


2

Повна відповідь з аргументами була б:

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

і це створить абсолютний URL


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

0

Може це (?):

<%= 
  Request.Url.GetLeftPart(UriPartial.Authority) + 
  Url.Action("Action1", "Controller2", new {param1="bla", param2="blabla" })
%>

0

env: версія ядра dotnet 1.0.4

Url.Action("Join",null, null,Context.Request.IsHttps?"https":"http");
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.