Как я могу получить базовый URL моего веб-приложения в ASP.NET MVC?

300

Как я могу быстро определить, какой корневой URL-адрес для моего приложения ASP.NET MVC? То есть, если IIS настроен для обслуживания моего приложения по адресу http://example.com/foo/bar , то я хотел бы иметь возможность получить этот URL надежным способом, не требующим получения текущего URL из запросить и нарезать его каким-нибудь хрупким способом, который сломается, если я перенаправлю свое действие.

Причина, по которой мне нужен базовый URL, заключается в том, что это веб-приложение вызывает другой, которому нужен корень для веб-приложения вызывающей стороны для целей обратного вызова.

Бенджамин Поллак
источник

Ответы:

399

Предполагая, что у вас есть объект Request, вы можете использовать:

string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, Url.Content("~"));

Если он недоступен, вы можете добраться до него через контекст:

var request = HttpContext.Current.Request
tghw
источник
8
Что такое urlHelper.Content("~")? Как мне создать определение urlHelper? Спасибо!
Максим Заславский
31
@ Максим, вы можете заменить Url.Content ("~")
UpTheCreek,
13
То, что я в конечном итоге использовал:var request = HttpContext.Current.Request; urlBase = string.Format("{0}://{1}{2}", request.Url.Scheme, request.Url.Authority, (new System.Web.Mvc.UrlHelper(request.RequestContext)).Content("~"));
Питер
7
Для MVC 4 я используюControllerContext.RequestContext.HttpContext.Request
row1
7
@Url.Content("~")разрешается в "/", который не является базовым URL.
Эндрю Хоффман
114

Так что ни один из перечисленных здесь не работал для меня, но, используя несколько ответов, я получил кое-что работающее:

public string GetBaseUrl()
{
    var request = HttpContext.Current.Request;
    var appUrl = HttpRuntime.AppDomainAppVirtualPath;

    if (appUrl != "/") 
        appUrl = "/" + appUrl;

    var baseUrl = string.Format("{0}://{1}{2}", request.Url.Scheme, request.Url.Authority, appUrl);

    return baseUrl;
}

Обновление для ASP.NET Core / MVC 6:

ASP.NET Coreделает этот процесс немного более болезненным, особенно если вы глубоко в своем коде. У вас есть 2 варианта, чтобы добраться доHttpContext

1) Передайте это от вашего controller:

var model = new MyClass(HttpContext);

затем в model:

private HttpContext currentContext;

public MyClass(HttpContext currentContext)
{
    this.currentContext = currentContext;
}

2) Возможно, более чистый способ - внедрить его в ваш класс, который начинается с регистрации типов в вашем классе. Startup:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    services.AddTransient<MyClass, MyClass>();
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}

тогда сделайте это для вас так:

private HttpContext currentContext;

public MyClass(IHttpContextAccessor httpContextAccessor)
{
    currentContext = httpContextAccessor.HttpContext;
}

в любом случае, вот обновление для .NET Core GetBaseUrl():

public string GetBaseUrl()
{
    var request = currentContext.Request;

    var host = request.Host.ToUriComponent();

    var pathBase = request.PathBase.ToUriComponent();

    return $"{request.Scheme}://{host}{pathBase}";
}
Серж Саган
источник
Где вы положили этот метод?
Джош Дин
3
Это действительно зависит от того, как часто вам нужно его использовать ... если это одноразовое соглашение, просто поместите его в класс, где вам нужны эти данные, если вы планируете использовать его в нескольких классах в своем приложении, тогда я использую папка вызывается Helpersв основе моего приложения, у меня есть staticкласс, Staticsи я помещаю функции, подобные приведенным выше ... просто убедитесь, что вы изменили вышеприведенное с public string GetBaseUrl()наpublic static string GetBaseUrl()
Серж Саган
В качестве обновления я больше не использую класс под названием Statics, вместо этого он разбит на несколько частей для более специфического использования, поэтому в этом случае это войдет в мой UrlHelperкласс
Серж Саган
1
Из всех вариантов, которые я нашел, это единственный, который действительно работал для меня. Ваш # 2 это. Огромное спасибо!
adeldegan
2
Я проголосовал за это, потому что он единственный, кто упомянул PathBase, а это именно то, что мне было нужно. Спасибо!
Дейв
69

В коде:

Url.Content("~/");

Синтаксис бритвы MVC3:

@Url.Content("~/")
mxasim
источник
11
Это хорошо для использования на страницах Razor, но если вы пытаетесь передать URL во внешний источник, он не даст вам полный URL.
Крильгар,
5
Это не работает Это просто добавит /вместо фактического имени.
Mrchief
2
Где находится Code, Urlвам сразу же может помочь помощник? Может быть, только в Controller. Конечно, не в том ViewModelили ином месте, classгде это может вам понадобиться ..
Серж Саган
43

Может быть, это расширение или модификация ответов, опубликованных здесь, но я использую просто следующую строку, и это работает:

Request.Url.GetLeftPart(UriPartial.Authority) + Url.Content("~")

Когда мой путь: http://host/iis_foldername/controller/action
тогда я получаю:http://host/iis_foldername/

Бронек
источник
26

Следующий фрагмент хорошо работает для меня в MVC4 и не нуждается в HttpContextдоступном:

System.Web.HttpRuntime.AppDomainAppVirtualPath
user666142
источник
Кажется, работает в MVC3 тоже. Я использую его jQuery.load()для создания URL для контроллера и действия, которое я хочу вызвать: $('#myplaceholder').load('@(Html.Raw(HttpRuntime.AppDomainAppVirtualPath))/MyController/MyAction', ...);
Kjell Rilbe
Почему ты бы так поступил? вместо вызова Url.Action?
BlackTigerX
4
Не работает при развертывании в Azure. В этом сценарии работают ответы с более высоким рейтингом.
Джефф Данлоп
25

Хитрость в том, чтобы полагаться на IIS, заключается в том, что привязки IIS могут отличаться от ваших общедоступных URL-адресов (я смотрю на WCF), особенно на производственных машинах с несколькими компьютерами. Я склоняюсь к использованию конфигурации для явного определения «базового» URL-адреса для внешних целей, поскольку он имеет тенденцию быть немного более успешным, чем извлечение его из объекта Request.

Уайетт Барнетт
источник
2
Также верно для серверов за балансировщиками нагрузки или прокси.
Измаил
20

Для абсолютного базового URL используйте это. Работает как с HTTP и HTTPS.

new Uri(Request.Url, Url.Content("~"))
Арни
источник
15

Это преобразование свойства asp.net в MVC . Это почти все пение, все танцы, получение корневого метода URL.

Объявите вспомогательный класс:

namespace MyTestProject.Helpers
{
    using System.Web;

    public static class PathHelper
    {
        public static string FullyQualifiedApplicationPath(HttpRequestBase httpRequestBase)
        {
            string appPath = string.Empty;

            if (httpRequestBase != null)
            {
                //Formatting the fully qualified website url/name
                appPath = string.Format("{0}://{1}{2}{3}",
                            httpRequestBase.Url.Scheme,
                            httpRequestBase.Url.Host,
                            httpRequestBase.Url.Port == 80 ? string.Empty : ":" + httpRequestBase.Url.Port,
                            httpRequestBase.ApplicationPath);
            }

            if (!appPath.EndsWith("/"))
            {
                appPath += "/";
            }

            return appPath;
        }
    }
}

Использование:

Для использования с контроллера:

PathHelper.FullyQualifiedApplicationPath(ControllerContext.RequestContext.HttpContext.Request)

Чтобы использовать в представлении:

@using MyTestProject.Helpers

PathHelper.FullyQualifiedApplicationPath(Request)
Пол Захра
источник
1
Это единственный ответ, который учитывает возможность работы сайта на порте, отличном от 80. Насколько мне известно, все остальные ответы небезопасны. Спасибо!
jebar8
12

В MVC _Layout.cshtml:

<base href="@Request.GetBaseUrl()" />

Вот что мы используем!

public static class ExtensionMethods
{
public static string GetBaseUrl(this HttpRequestBase request)
        {
          if (request.Url == (Uri) null)
            return string.Empty;
          else
            return request.Url.Scheme + "://" + request.Url.Authority + VirtualPathUtility.ToAbsolute("~/");
        }
}
katibaer
источник
+1 за использование <base>. Также вы можете опустить Схему, чтобы она работала с http или https. Это означает, что вы можете начать URL с //.
Джесс
5

Это прекрасно работает для меня (также с балансировщиком нагрузки):

@{
    var urlHelper = new UrlHelper(Html.ViewContext.RequestContext);
    var baseurl = urlHelper.Content(“~”);
}

<script>
    var base_url = "@baseurl";
</script>

Особенно, если вы используете нестандартные номера портов, использование Request.Url.Authority на первый взгляд кажется хорошим лидером, но в среде LB терпит неудачу.

Тадей Грегорчич
источник
3

У вас может быть статический метод, который просматривает HttpContext.Current и решает, какой URL-адрес использовать (сервер разработки или работающий сервер) в зависимости от идентификатора хоста. HttpContext может даже предложить более простой способ сделать это, но это первый вариант, который я нашел, и он работает нормально.

Адриан Григоре
источник
3

Вы можете использовать следующий скрипт:

<script type="text/javascript">
    var BASE_URL = '<%= ResolveUrl("~/") %>';
</script>
Андрус
источник
3

Для ASP.NET MVC 4 это немного отличается:

string url = HttpContext.Request.Url.AbsoluteUri;
Фернандо Веццали
источник
3

Это работает в ASP .NET MVC 4 В любом действии контроллера вы можете написать: 1stline получает весь URL-адрес + строку запроса. 2-я строка удаляет локальный путь и запрос, последний символ '/'. 3-я строка добавляет символ «/» в последнюю позицию.

Uri url = System.Web.HttpContext.Current.Request.Url;
string UrlLink = url.OriginalString.Replace(url.PathAndQuery,"");
UrlLink = String.Concat(UrlLink,"/" );
Мухаммед Асикуззаман
источник
3

в простом HTML и ASP.NET или ASP.NET MVC, если вы используете тег:

<a href="~/#about">About us</a>
Рави Ананд
источник
3

Для URL с псевдонимом приложения, например http://example.com/appAlias/ ... Вы можете попробовать это:

var req = HttpContext.Current.Request;
string baseUrl = string.Format("{0}://{1}/{2}", req.Url.Scheme, req.Url.Authority, req.ApplicationPath);
Яцек Гзель
источник
3

На самой веб-странице:

<input type="hidden" id="basePath" value="@string.Format("{0}://{1}{2}",
  HttpContext.Current.Request.Url.Scheme,
  HttpContext.Current.Request.Url.Authority,
  Url.Content("~"))" />

В JavaScript:

function getReportFormGeneratorPath() {
  var formPath = $('#reportForm').attr('action');
  var newPath = $("#basePath").val() + formPath;
  return newPath;
}

Это работает для моего проекта MVC, надеюсь, это поможет

Андрей Дей
источник
@hemp Отредактировал, но не голосовал за это? Надеюсь, что очки ценны для вас
Эндрю Дэй
Этот вопрос и связанные с ним ответы не помогли решить мою конкретную проблему, поэтому я не пытался голосовать за них. Я отредактировал этот, потому что случайно увидел его и подумал, что это может быть достойный ответ, если он был правильно отформатирован. Просто пытаюсь быть хорошим гражданином.
конопля
Кроме того, нет очков репутации, полученных за редактирование ответа.
конопля
2

Я положил это в голову моего _Layout.cshtml

 <base href="~/" />
ошибочный кинематограф
источник
2

Может быть, это лучшее решение.

@{
   var baseUrl = @Request.Host("/");
}

с помощью

<a href="@baseUrl" class="link">Base URL</a>
РС
источник
1
Я не тестировал, но сомневаюсь, что это сработает, если базовый URL-адрес является виртуальным. то есть. localhost / myApp
emragins
1

Для MVC 4:

String.Format("{0}://{1}{2}", Url.Request.RequestUri.Scheme, Url.Request.RequestUri.Authority, ControllerContext.Configuration.VirtualPathRoot);
Ремигиюс Панкявичюс
источник
1

Следующее сработало для меня

var request = HttpContext.Request;
                        var appUrl = System.Web.HttpRuntime.AppDomainAppVirtualPath;

                        if (appUrl != "/")
                            appUrl = "/" + appUrl + "/";

                        var newUrl = string.Format("{0}://{1}{2}{3}/{4}", request.Url.Scheme, request.UrlReferrer.Host, appUrl, "Controller", "Action");
Venu
источник
1

Это было мое решение (с использованием .net core 3.1, в контроллере API):

string baseUrl = $"{Request.Scheme}://{Request.Headers.Where(h => h.Key == "Host").First().Value}";
Barnebyte
источник
0

Просто в одну строку получи BaseUrl

string baseUrl = new Uri(Request.Url, Url.Content("~")).AbsoluteUri;

//output example: https://stackoverflow.com
Захид Танвир
источник
0

Также вы можете использовать это. Для бритвенных страниц лучше использовать его, чем другие.

https://ml-software.ch/posts/getting-the-base-url-for-an-asp-net-core-mvc-web-application-in-your-static-javascript-files

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <base href='@Url.AbsoluteContent("~/")'>
    <title>@ViewBag.Title - ASP.NET Core Web Application</title>
    <!-- ... -->
</head>
<body>
Махмут ЭФЕ
источник
0

добавьте эту функцию в статический класс в проект как служебный класс:

Содержание utility.cs :

public static class Utility
{
    public static string GetBaseUrl()
    {
        var request = HttpContext.Current.Request;
        var urlHelper = new UrlHelper(request.RequestContext);
        var baseUrl = $"{request.Url.Scheme}://{request.Url.Authority}{urlHelper.Content("~")}";
        return baseUrl;
    }
}

используйте этот код в любом месте и наслаждайтесь им:

var baseUrl = Utility.GetBaseUrl();
DLMAN
источник