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

226

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

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

Теги:
asp.net-mvc
iis

21 ответ

307
Лучший ответ

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

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

Если он недоступен, вы можете перейти к нему через контекст:

var request = HttpContext.Current.Request
  • 0
    Я попробовал это, но ни HttpContext.Current.Request.Authority, ни HttpContext.Current.Request.Scheme не были определены.
  • 7
    Что такое urlHelper.Content("~") ? Как мне создать определение urlHelper ? Спасибо!
Показать ещё 11 комментариев
74

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

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}";
}
  • 0
    Где вы положили этот метод?
  • 3
    Это действительно зависит от того, как часто вам нужно его использовать ... если это одноразовое соглашение, просто поместите его в класс, где вам нужны эти данные, если вы планируете использовать его в нескольких классах в своем приложении, тогда я использую папка под названием Helpers в базе моего приложения, у меня есть static класс под названием Statics и я помещаю туда функции, подобные описанным выше ... просто убедитесь, что вы изменили вышеприведенное с public string GetBaseUrl() на public static string GetBaseUrl()
Показать ещё 3 комментария
46

В коде:

Url.Content("~/");

Синтаксис Razor MVC3:

@Url.Content("~/")
  • 11
    Это хорошо для использования на страницах Razor, но если вы пытаетесь передать URL во внешний источник, он не даст вам полный URL.
  • 4
    Не работает Это просто добавит / вместо фактического имени.
Показать ещё 1 комментарий
30

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

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

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

24

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

  • 1
    кажется разумным и менее склонным к ошибкам конфигурации.
  • 2
    Также верно для серверов за балансировщиками нагрузки или прокси.
20

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

System.Web.HttpRuntime.AppDomainAppVirtualPath
  • 0
    Кажется, работает в MVC3 тоже. Я использую его в jQuery.load() для создания URL-адреса контроллера и действия, которое я хочу вызвать: $('#myplaceholder').load('@(Html.Raw(HttpRuntime.AppDomainAppVirtualPath))/MyController/MyAction', ...);
  • 0
    Почему ты бы так поступил? вместо вызова Url.Action?
Показать ещё 1 комментарий
16

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

new Uri(Request.Url, Url.Content("~"))
13

Это преобразование свойства 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. Насколько мне известно, все остальные ответы небезопасны. Спасибо!
11

В 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("~/");
        }
}
  • 1
    А ури есть? эм ...
  • 0
    +1 за использование <base> . Также вы можете опустить Схему, чтобы она работала с http или https. Это означает, что вы можете начать URL с // .
4

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

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

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

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

2

Для 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);
2

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

<a href="~/#about">About us</a>
2

Это работает в ASP.NET MVC 4  В любом действии контроллера вы можете написать: 1stline получает весь url + Query String. Вторая строка удаляет локальный путь и запрос, последний символ "/". Третья строка добавляет символ "/" в последнюю позицию.

Uri url = System.Web.HttpContext.Current.Request.Url;
string UrlLink = url.OriginalString.Replace(url.PathAndQuery,"");
UrlLink = String.Concat(UrlLink,"/" );
2

Для ASP.NET MVC 4 это немного другое:

string url = HttpContext.Request.Url.AbsoluteUri;
2

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

<script type="text/javascript">
    var BASE_URL = '<%= ResolveUrl("~/") %>';
</script>
2

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

1

Возможно, это лучшее решение.

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

используя

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

Для MVC 4:

String.Format("{0}://{1}{2}", Url.Request.RequestUri.Scheme, Url.Request.RequestUri.Authority, ControllerContext.Configuration.VirtualPathRoot);
0

Для ASP.NET Core 2:

private string SiteRoot => $"{Request.Scheme}://{Request.Host}{Request.PathBase}";
0

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

 <base href="~/" />
0

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

<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, надеюсь, что он поможет

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню