¿Cuál es el mejor método en ASP.NET para obtener el dominio actual?

102

Me pregunto cuál es la mejor manera de obtener el dominio actual en ASP.NET.

Por ejemplo:

http://www.domainname.com/subdir/ debería producir http://www.domainname.com http://www.sub.domainname.com/subdir/ debería producir http://sub.domainname.com

Como guía, debería poder agregar una URL como "/Folder/Content/filename.html" (digamos que la generada por Url.RouteUrl () en ASP.NET MVC) directamente en la URL y debería funcionar.

Matt Mitchell
fuente
3
Tenga en cuenta que el "dominio actual" aquí es en realidad lo que el usuario-agente consumidor utilizó para acceder a su sitio, que en muchos casos es diferente de la "URL oficial" de su sitio, así como de lo que el usuario final pudo haber ingresado en su navegador ( proxy inverso, proxy directo, nombre de host interno, dirección IP, ...).
bzlm
1
Entonces, ¿hay alguna manera de obtener la "URL oficial" (la de IIS?)
Matt Mitchell

Respuestas:

186

Misma respuesta que la de MattMitchell pero con algunas modificaciones. En su lugar, esto busca el puerto predeterminado.

Editar: sintaxis actualizada y uso Request.Url.Authoritycomo se sugiere

$"{Request.Url.Scheme}{System.Uri.SchemeDelimiter}{Request.Url.Authority}"
Carlos Muñoz
fuente
3
¿Hay un campo definido en .NET que pueda usar en lugar de ":"? ¿Algo como System.Uri.PortDelimiter? Ya sabes, solo por coherencia. :)
Jan Aagaard
2
No que yo sepa, Jan Aagaard, pero siempre puedes hacer uno localmente. Hago eso para la mayoría de cuerdas y números "mágicos". Para el caso, entonces usaría string.Empty en lugar de "" en la respuesta de Carlos;)
vbullinger
8
Puede usar Request.Url.Authoritycomo sugirió Korayem en lugar de Request.Url.Hosty Request.Url.Port.
Schmalls
4
En lugar de concatenar cadenas, debería utilizar la clase System.UriBuilder.
BrainSlugs83
3
@MattMitchell, parece que los problemas con la Autoridad no se han fundado, es el equivalente de Host + ":" + Puerto, consulte el código fuente dotnetframework.org/default.aspx/DotNET/DotNET/8@0/untmp/…
Giuseppe Romagnuolo
40

Según este enlace, un buen punto de partida es:

Request.Url.Scheme + System.Uri.SchemeDelimiter + Request.Url.Host 

Sin embargo, si el dominio es http://www.domainname.com:500, esto fallará.

Algo como lo siguiente es tentador para resolver esto:

int defaultPort = Request.IsSecureConnection ? 443 : 80;
Request.Url.Scheme + System.Uri.SchemeDelimiter + Request.Url.Host 
  + (Request.Url.Port != defaultPort ? ":" + Request.Url.Port : "");

Sin embargo, los puertos 80 y 443 dependerán de la configuración.

Como tal, debe usar IsDefaultPortcomo en la Respuesta aceptada anterior de Carlos Muñoz.

Matt Mitchell
fuente
1
¿Por qué asumir el puerto 80 aquí? Si elimina esa suposición, el código parece un comodín. Cuando asume el puerto 80, fallará en muchos escenarios (vea los comentarios sobre otras respuestas). Si desea eliminar el número de puerto, si es posible, debe verificar que el número de puerto sea el predeterminado para el esquema en cuestión y que el esquema admita números de puerto predeterminados.
bzlm
Sí, vea la nota de que el puerto 80 puede ser una mala idea. Sin embargo, no conozco otra forma de evitar esto, por lo que mencioné que tendrá que depender de la configuración.
Matt Mitchell
1
No sé si esto ayudará o no, pero también puede intentar: if Request.IsSecureConnection para determinar si se usa HTTPS o no.
Erick Brown
1
@EricBrown - Sí, esta respuesta no es excelente en retropsect 5 años después. Yo iría con la respuesta aceptada de Carlos Muñoz para evitar ese problema.
Matt Mitchell
29
Request.Url.GetLeftPart(UriPartial.Authority)

Este es el esquema incluido.

izlence
fuente
23
Me encantaría haber estado en la reunión cuando se les ocurrió ese nombre
Simon_Weaver
20

¡ADVERTENCIA! Para cualquiera que use Current.Request .Url.Host. Comprenda que está trabajando en base a la SOLICITUD ACTUAL y que la solicitud actual NO SIEMPRE estará con su servidor y, a veces, puede estar con otros servidores.

Entonces, si usa esto en algo como Application_BeginRequest () en Global.asax, entonces el 99.9% del tiempo estará bien, pero el 0.1% puede obtener algo diferente al nombre de host de su propio servidor.

Un buen ejemplo de esto es algo que descubrí no hace mucho. Mi servidor tiende a golpear http://proxyjudge1.proxyfire.net/fastenv de vez en cuando. Application_BeginRequest () maneja con gusto esta solicitud, por lo que si llama a Request.Url.Host cuando realiza esta solicitud, obtendrá de vuelta proxyjudge1.proxyfire.net. Algunos de ustedes pueden estar pensando "no duh", pero vale la pena señalarlo porque fue un error muy difícil de notar ya que solo sucedió el 0.1% de las veces: P

Este error me ha obligado a insertar mi host de dominio como una cadena en los archivos de configuración.

Thirlan
fuente
Hizo exactamente lo mismo. Mi dominio está en web.config ahora.
Korayem
i creo que entiendo, sin embargo - ¿Por qué el servidor de golpe proxyfire? ¿Ese es tu sitio? Pero, en general, tiene sentido: el uso de un objeto específico de la solicitud durante un evento específico de la aplicación puede no funcionar demasiado bien. ¿Existe algún peligro en un evento de solicitud específico, como un evento de ciclo de vida de la página (Page.LoadCompleted, etc.)?
mlhDev
No investigué demasiado en cuanto a por qué se estaba resolviendo en proxyfire. Ciertamente no era mi sitio, pero me indicó que Current.Request.Url no era 100% confiable. Después de mucha investigación, también descubrí que determinar dinámicamente su nombre de host no es fácil, debido a las múltiples tarjetas NIC, IP y nombres de dominio que se resuelven en la misma IP. En cuanto a su otra pregunta Matt, no estoy seguro de lo que quiere decir: (
Thirlan
¿Entonces esto solo ocurrió en Application_BeginRequest? No veo cómo IIS podría haber enviado esta solicitud a su aplicación a menos que no tenga un encabezado de host configurado tal vez.
Simon_Weaver
@Thirlan: estoy tratando de depurar un problema que suena similar a esto. Estoy tratando de obtener el subdominio usando Request.Url.Host y 'por lo general' funciona bien, pero no siempre. ¿Realmente hay alguna forma de evitar esto? ¿Algo más en la solicitud que pueda ser correcto?
Scojomodena
14

Por qué no usar

Request.Url.Authority

Devuelve todo el dominio Y el puerto.

Aún necesita calcular http o https

Korayem
fuente
2
Esto también funciona. Para "calcular" http o https, simplemente coloque "//" antes. Por ejemplo, se leería como href = "// @ Request.Url.Authority ..."
EdwardM
2

Manera simple y corta (admite esquema, dominio y puerto):

Utilizar Request.GetFullDomain()

// Add this class to your project
public static class HttpRequestExtensions{
    public static string GetFullDomain(this HttpRequestBase request)
    {
        var uri= request?.UrlReferrer;
        if (uri== null)
            return string.Empty;
        return uri.Scheme + Uri.SchemeDelimiter + uri.Authority;
    }
}

// Now Use it like this:
Request.GetFullDomain();
// Example output:    https://www.example.com:5031
// Example output:    http://www.example.com:5031
// Example output:    https://www.example.com
RAM
fuente
1

De otra manera:


string domain;
Uri url = HttpContext.Current.Request.Url;
domain= url.AbsoluteUri.Replace(url.PathAndQuery, string.Empty);

fuente
¡Respuesta simple pero simplemente increíble!
Shiroy
1

Qué tal si:

NameValueCollection vars = HttpContext.Current.Request.ServerVariables;
string protocol = vars["SERVER_PORT_SECURE"] == "1" ? "https://" : "http://";
string domain = vars["SERVER_NAME"];
string port = vars["SERVER_PORT"];
Derek Lawless
fuente
0

Usando UriBuilder:

    var relativePath = ""; // or whatever-path-you-want
    var uriBuilder = new UriBuilder
    {
        Host = Request.Url.Host,
        Path = relativePath,
        Scheme = Request.Url.Scheme
    };

    if (!Request.Url.IsDefaultPort)
        uriBuilder.Port = Request.Url.Port;

    var fullPathToUse = uriBuilder.ToString();
Darren
fuente
-1

Qué tal si:

String domain = "http://" + Request.Url.Host
jwalkerjr
fuente
No está mal, pero ¿qué pasa si su sitio tiene páginas seguras, es decir, https: // ¿Qué pasa si su dominio no está alojado en el puerto 80?
Matt Mitchell