ASP.NET 中获取当前域名的最佳方法是什么?

104

3
请注意,“当前域名”实际上是指使用的用户代理访问您网站的域名,这在很多情况下与您网站的“官方网址”以及最终用户可能输入到浏览器中的内容(反向代理,正向代理,内部主机名,IP地址等)有所不同。 - bzlm
1
那么有没有一种方法可以获取“官方URL”(来自IIS的URL)? - Matt Mitchell
11个回答

190

与MattMitchell的答案相同,但有一些修改。这将检查默认端口。

编辑:更新语法并使用建议的Request.Url.Authority

$"{Request.Url.Scheme}{System.Uri.SchemeDelimiter}{Request.Url.Authority}"

3
在.NET中是否有一个字段可以替代“:”?类似于System.Uri.PortDelimiter这样的东西,只是为了保持一致性。 :) - Jan Aagaard
2
据我所知,Jan Aagaard,目前还没有这样的功能,但您可以在本地创建一个。对于大多数“神奇”的字符串和数字,我都是这样做的。因此,在Carlos的答案中,您将使用string.Empty而不是“”。 - vbullinger
8
你可以像Korayem建议的那样使用Request.Url.Authority,而不是Request.Url.HostRequest.Url.Port - Schmalls
4
应该使用 System.UriBuilder 类来代替字符串拼接。 - BrainSlugs83
3
@MattMitchell,看起来没发现权限问题,这等同于 Host + ":" + Port,参见源代码http://www.dotnetframework.org/default.aspx/DotNET/DotNET/8@0/untmp/whidbey/REDBITS/ndp/fx/src/Net/System/URI@cs/9/URI@cs。 - Giuseppe Romagnuolo
显示剩余2条评论

42
根据此链接,一个好的起点是:
Request.Url.Scheme + System.Uri.SchemeDelimiter + Request.Url.Host 

然而,如果域名是 http://www.domainname.com:500 ,则会失败。
为了解决这个问题,类似以下的方法是很诱人的:
int defaultPort = Request.IsSecureConnection ? 443 : 80;
Request.Url.Scheme + System.Uri.SchemeDelimiter + Request.Url.Host 
  + (Request.Url.Port != defaultPort ? ":" + Request.Url.Port : "");

然而,端口80和443将取决于配置。

因此,您应该像接受的答案中的Carlos Muñoz一样使用IsDefaultPort


1
为什么要在这里假设端口80?如果你去掉这个假设,代码看起来很拖沓。当你假设端口 80 时,在许多情况下你将失败(请参见其他答案的评论)。如果你想尽可能地去掉端口号,你必须检查该端口号是否是相关协议的默认端口,并且该协议支持默认端口号。 - bzlm
是的,请注意端口80可能不是一个好主意。但我不知道有什么其他的解决办法,这就是为什么我提到它需要根据配置来确定。 - Matt Mitchell
1
我不知道这是否有帮助,但你也可以尝试使用 if Request.IsSecureConnection 来确定是否使用了 HTTPS。 - Erick Brown
1
@EricBrown - 是的,在回顾五年后,这个答案已经不是很好了。我会选择Carlos Muñoz所接受的答案来避免这个问题。 - Matt Mitchell

29
Request.Url.GetLeftPart(UriPartial.Authority)

这是包含的方案。


20

警告!使用Current.Request.Url.Host的所有用户请注意,您正在基于当前请求工作,而当前请求并不总是与您的服务器在一起,有时可能会与其他服务器在一起。

因此,如果您将其用于 Application_BeginRequest() 在 Global.asax 中等类似情况中,则在99.9% 的情况下都可以正常使用,但也会有0.1% 的概率会得到与您自己服务器的主机名不同的结果。

最近我发现了一个很好的例子。我的服务器偶尔会访问http://proxyjudge1.proxyfire.net/fastenv。Application_BeginRequest() 会处理这个请求,因此如果您在进行此请求时调用 Request.Url.Host,则会返回proxyjudge1.proxyfire.net。其中一些人可能认为“那当然”,但这值得注意,因为它只会在0.1% 的情况下发生 : P

这个bug迫使我将域主机作为字符串插入到配置文件中。


完全一样。现在我的域名已经在web.config文件中了。 - Korayem
认为 我理解了,但是 - 为什么你的服务器会访问ProxyFire呢?那是你的网站吗?但总的来说,是有道理的 - 在应用程序特定事件期间使用请求特定对象可能不太有效。在请求特定事件中是否存在危险,例如页面生命周期事件(Page.LoadCompleted等)? - mlhDev
我没有深入调查为什么它会解析到proxyfire。这肯定不是我的网站,但它确实向我表明Current.Request.Url并不完全可靠。经过大量研究,我还发现动态确定主机名并不容易,因为存在多个NIC卡、IP和解析到同一IP的域名。至于你的另一个问题Matt,我不确定你的意思 :( - Thirlan
这只会在Application_BeginRequest中发生吗?我不明白除非你没有设置主机头,否则IIS怎么可能将此请求发送到您的应用程序? - Simon_Weaver
@Thirlan - 我正在尝试调试一个听起来类似的问题。我正在尝试使用Request.Url.Host获取子域名,通常情况下效果很好,但并非总是如此。是否真的有其他方法可以解决这个问题?比如请求中可能正确的其他内容? - scojomodena
我当时阅读了很多相关资料,不幸的是唯一可靠的方法就是硬编码。 - Thirlan

14

为什么不使用

Request.Url.Authority

它返回完整的域名和端口。

你仍需要确定是http还是https。


2
这也可以。要“解析”http或https,只需在它之前加上“//”。所以例如,它会被写成href="//@Request.Url.Authority..." - EdwardM

3

简单而且简短的方法(支持架构,域名和端口):

使用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://example.com:5031
// Example output:    http://example.com:5031

1

另一种方式:


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

1

这样怎么样:

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"];

1
在Asp.Net Core 3.1中,如果您想获取完整的域名,需要执行以下步骤:
步骤1:定义变量。
private readonly IHttpContextAccessor _contextAccessor;

步骤2:将DI注入构造函数中。
public SomeClass(IHttpContextAccessor contextAccessor)
{
    _contextAccessor = contextAccessor;
}

步骤3:在您的类中添加此方法:

private string GenerateFullDomain()
{
    string domain = _contextAccessor.HttpContext.Request.Host.Value;
    string scheme = _contextAccessor.HttpContext.Request.Scheme;
    string delimiter = System.Uri.SchemeDelimiter;
    string fullDomainToUse = scheme + delimiter + domain;
    return fullDomainToUse;
}
//Examples of usage GenerateFullDomain() method:
//https://example.com:5031
//http://example.com:5031

0
使用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();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接