Como posso obter o URL base do meu aplicativo da web no ASP.NET MVC?

300

Como posso determinar rapidamente qual é o URL raiz do meu aplicativo ASP.NET MVC? Ou seja, se o IIS estiver configurado para atender meu aplicativo em http://example.com/foo/bar , eu gostaria de obter esse URL de uma maneira confiável, que não envolva a obtenção do URL atual do solicitar e desmembrá-lo de alguma maneira frágil que quebre se eu redirecionar minha ação.

O motivo pelo qual eu preciso da URL base é que esse aplicativo Web chama outro que precisa da raiz do aplicativo Web chamador para fins de retorno de chamada.

Benjamin Pollack
fonte

Respostas:

399

Supondo que você tenha um objeto Request disponível, você pode usar:

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

Se não estiver disponível, você poderá acessá-lo através do contexto:

var request = HttpContext.Current.Request
tghw
fonte
8
O que é urlHelper.Content("~")? Como crio define urlHelper? Obrigado!
Maxim Zaslavsky
31
@ Maxim, você provavelmente pode substituir Url.Content ("~")
UpTheCreek
13
O que eu acabei usando: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("~"));
Peter
7
Para MVC 4 eu usoControllerContext.RequestContext.HttpContext.Request
row1
7
@Url.Content("~")resolve para "/", que não é o URL base.
Andrew Hoffman
114

Portanto, nenhum dos listados aqui funcionou para mim, mas usando algumas das respostas, obtive algo funcionando:

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

Atualização para o ASP.NET Core / MVC 6:

ASP.NET Coretorna esse processo um pouco mais doloroso, especialmente se você está profundamente envolvido no seu código. Você tem 2 opções para chegar aoHttpContext

1) Passe do seu controller:

var model = new MyClass(HttpContext);

então em model:

private HttpContext currentContext;

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

2) Talvez a maneira mais limpa seja injetá-lo na sua turma, que começa com o registro dos tipos no seu Startup:

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

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

injete-o assim:

private HttpContext currentContext;

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

nos dois casos, eis a atualização para .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}";
}
Serj Sagan
fonte
Onde você colocou esse método?
Josh Dean #
3
Isso realmente depende da frequência com que você precisa usá-lo ... se esse é um acordo de uso único, basta colocá-lo na classe em que você precisa desses dados, se você antecipar usá-lo em várias classes no seu aplicativo, então eu uso um pasta chamada Helpersna base do meu aplicativo, eu tenho uma staticclasse chamada Staticse coloco funções como as anteriores lá ... apenas certifique-se de alterar as public string GetBaseUrl()public static string GetBaseUrl()
opções
Como uma atualização, eu já não usar uma classe chamada Statics, em vez eu tê-lo separado em mais usos específicos, por isso, neste caso, isso seria ir para a minha UrlHelperclasse
Serj Sagan
1
De todas as opções que encontrei, essa é a única que realmente funcionou para mim. Seu # 2 que é. Muitíssimo obrigado!
adeldegan
2
Promovido isso porque é o único a mencionar o PathBase, que é exatamente o que eu precisava. Obrigado!
31419 Dave
69

Em código:

Url.Content("~/");

Sintaxe do MVC3 Razor:

@Url.Content("~/")
mxasim
fonte
11
Isso é bom para usar nas páginas do Razor, mas se você estiver tentando passar o URL para uma fonte externa, ele não fornecerá o URL completo.
precisa saber é o seguinte
5
Isso não funciona. Apenas adicionará em /vez do nome real.
Mrchief
2
Onde o Code está Urldisponível para o ajudante logo de cara? Talvez apenas no Controller. Certamente não no ViewModelou qualquer outro classonde você pode precisar isso ..
Serj Sagan
43

Talvez seja extensão ou modificação das respostas postadas aqui, mas eu uso simplesmente a seguinte linha e funciona:

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

Quando meu caminho é: http://host/iis_foldername/controller/action
então eu recebo:http://host/iis_foldername/

Bronek
fonte
26

O seguinte snippet funciona muito bem para mim no MVC4 e não precisa de um HttpContextdisponível:

System.Web.HttpRuntime.AppDomainAppVirtualPath
user666142
fonte
Parece funcionar também no MVC3. Eu uso-o jQuery.load()para construir a URL para o controlador e a ação que desejo chamar: $('#myplaceholder').load('@(Html.Raw(HttpRuntime.AppDomainAppVirtualPath))/MyController/MyAction', ...);
Kjell Rilbe 19/10/12
Por que você faria isso? em vez de chamar Url.Action?
BlackTigerX
4
Não funciona quando implantado no Azure. Respostas com classificação mais alta funcionam nesse cenário.
Jeff Dunlop
25

O truque para confiar no IIS é que as ligações do IIS podem ser diferentes dos seus URLs públicos (WCF, estou olhando para você), especialmente com máquinas de produção com hospedagem múltipla. Eu costumo usar vetor de configuração para definir explicitamente o URL "base" para fins externos, pois isso tende a ser um pouco mais bem-sucedido do que extraí-lo do objeto Request.

Wyatt Barnett
fonte
2
Isso também se aplica aos servidores que utilizam balanceadores de carga ou proxies.
Ishmaeel
20

Para um URL base absoluto, use isso. Funciona com HTTP e HTTPS.

new Uri(Request.Url, Url.Content("~"))
arni
fonte
15

Esta é uma conversão de uma propriedade asp.net para MVC . É um método praticamente todo de cantar e dançar.

Declare uma classe auxiliar:

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

Uso:

Para usar de um controlador:

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

Para usar em uma exibição:

@using MyTestProject.Helpers

PathHelper.FullyQualifiedApplicationPath(Request)
Paul Zahra
fonte
1
Essa é a única resposta que explica a possibilidade de um site ser executado em uma porta que não seja 80. Todas as outras respostas são inseguras para mim. Obrigado!
jebar8
12

No MVC _Layout.cshtml:

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

É isso que usamos!

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
fonte
+1 para usar <base>. Além disso, você pode omitir o esquema para que ele funcione com http ou https. Isso significa que você pode iniciar o URL //.
Jess
5

Isso funciona bem para mim (também com um balanceador de carga):

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

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

Especialmente se você estiver usando números de porta não padrão, usar Request.Url.Authority parecerá um bom lead no início, mas falhará em um ambiente LB.

Tadej Gregorcic
fonte
3

Você pode ter um método estático que analise HttpContext.Current e decida qual URL usar (servidor de desenvolvimento ou ativo), dependendo do ID do host. O HttpContext pode até oferecer uma maneira mais fácil de fazer isso, mas esta é a primeira opção que encontrei e funciona bem.

Adrian Grigore
fonte
3

Você pode usar o seguinte script na exibição:

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

Para o ASP.NET MVC 4, é um pouco diferente:

string url = HttpContext.Request.Url.AbsoluteUri;
Fernando Vezzali
fonte
3

Isso está funcionando no ASP .NET MVC 4 Em qualquer ação do controlador, você pode escrever: 1stline obtém o URL inteiro + Query String. 2a linha remover caminho local e consulta, último símbolo '/'. Terceira linha, adicione o símbolo '/' na última posição.

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

em html simples e ASP.NET ou ASP.NET MVC, se você estiver usando a tag:

<a href="~/#about">About us</a>
Ravi Anand
fonte
3

Para URLs com alias de aplicação como http://example.com/appAlias/ ... Você pode tentar o seguinte:

var req = HttpContext.Current.Request;
string baseUrl = string.Format("{0}://{1}/{2}", req.Url.Scheme, req.Url.Authority, req.ApplicationPath);
Jacek Gzel
fonte
3

Na própria página da web:

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

No javascript:

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

Isso funciona para o meu projeto MVC, espero que ajude

Andrew Day
fonte
@hemp Editou, mas não votou nele? Espero que os pontos são importantes para você
Andrew Dia
Esta pergunta e as respostas associadas não foram úteis para o meu problema específico, por isso não tentei ou votei em nenhum deles. Editei este porque o vi e achei que poderia ser uma resposta decente se fosse formatado corretamente. Apenas tentando ser um bom cidadão.
cânhamo
Além disso, não há pontos de reputação ganhos para editar uma resposta.
cânhamo
2

Coloquei isso na cabeça do meu _Layout.cshtml

 <base href="~/" />
cineam errado
fonte
2

Talvez seja uma solução melhor.

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

usando

<a href="@baseUrl" class="link">Base URL</a>
em
fonte
1
Não testei, mas duvido que isso funcione quando o URL base for um virtual diretamente. ie localhost / myApp
emragins
1

Para MVC 4:

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

O seguinte funcionou solidamente para mim

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
fonte
1
@{
    var baseurl = Request.Url.Scheme + "://" + Request.Url.Host + ":" + Request.Url.Port + Url.Content("~");
}
@baseurl

--output http: // localhost: 49626 / TEST /

Jackdon Wang
fonte
1

Esta foi a minha solução (usando o .net core 3.1, em um controlador api):

string baseUrl = $"{Request.Scheme}://{Request.Headers.Where(h => h.Key == "Host").First().Value}";
Barnebyte
fonte
0

Simplesmente em uma linha, obtenha o BaseUrl

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

//output example: https://stackoverflow.com
Zahid Tanveer
fonte
0

adicione esta função na classe estática no projeto como classe de utilitário:

conteúdo 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;
    }
}

use este código em qualquer lugar e divirta-se:

var baseUrl = Utility.GetBaseUrl();
DLMAN
fonte