【问题标题】:What's the best method in ASP.NET to obtain the current domain?ASP.NET 中获取当前域的最佳方法是什么?
【发布时间】:2010-09-08 21:01:15
【问题描述】:

我想知道在 ASP.NET 中获取当前域的最佳方法是什么?

例如:

http://www.domainname.com/subdir/ 应该产生http://www.domainname.com http://www.sub.domainname.com/subdir/ 应该产生 http://sub.domainname.com

作为指导,我应该能够直接在 URL 上添加一个类似“/Folder/Content/filename.html”的 URL(比如由 ASP.NET MVC 中的 Url.RouteUrl() 生成),它应该可以工作.

【问题讨论】:

  • 请注意,这里的“当前域”实际上是消费用户代理用来访问您网站的内容,在许多情况下,这与您网站的“官方 URL”以及结尾不同用户可能已经输入了他们的浏览器(反向代理、正向代理、内部主机名、IP 地址……)。
  • 那么有没有办法获取“官方 URL”(来自 IIS 的那个?)

标签: asp.net asp.net-mvc domain-name


【解决方案1】:

根据this link,一个好的起点是:

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 将取决于配置。

因此,您应该使用IsDefaultPort,就像上面来自 Carlos Muñoz 的 Accepted Answer 一样。

【讨论】:

  • 为什么在这里假设端口 80?如果你去掉这个假设,代码看起来就像一个包罗万象的东西。当您假设端口 80 时,您将在许多情况下失败(请参阅 cmets on other anwers)。如果您想尽可能删除端口号,则必须检查该端口号是否是相关方案的默认端口号,并且该方案是否支持默认端口号。
  • 是的,请注意端口 80 可能是个坏主意。我不知道有什么其他方法可以解决这个问题,这就是为什么我提到它需要依赖于配置。
  • 我不知道这是否有帮助,但您也可以尝试:如果 Request.IsSecureConnection 来确定是否使用了 HTTPS?
  • @EricBrown - 是的,这个答案在 5 年后的回顾中并不是很好。为了避免这个问题,我会选择 Carlos Muñoz 接受的答案。
【解决方案2】:

怎么样:

String domain = "http://" + Request.Url.Host

【讨论】:

  • 不错,但是如果您的网站有安全页面,例如 https://,如果您的域没有托管在端口 80 上怎么办?
【解决方案3】:

怎么样:

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

【讨论】:

    【解决方案4】:

    另一种方式:

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

    【讨论】:

      【解决方案5】:

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

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

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

      【讨论】:

      • 在 .NET 中是否定义了一个字段,我可以使用它来代替“:”? System.Uri.PortDelimiter 之类的东西?你知道,只是为了保持一致。 :)
      • 我不知道,Jan Aagaard,但你总是可以在本地制作一个。我对大多数“魔术”字符串和数字都这样做。就此而言,您将在 Carlos 的回答中使用 string.Empty 而不是 "" ;)
      • 您可以按照 Korayem 的建议使用 Request.Url.Authority,而不是 Request.Url.HostRequest.Url.Port
      • 您应该使用 System.UriBuilder 类,而不是连接字符串。
      • @MattMitchell,好像不是Authority的问题,相当于Host + ":" + Port,看源码dotnetframework.org/default.aspx/DotNET/DotNET/8@0/untmp/…
      【解决方案6】:

      警告!致所有使用 Current.Request.Url.Host 的人。了解您正在根据当前请求工作,并且当前请求不会始终与您的服务器一起使用,有时可能与其他服务器一起使用。

      因此,如果您在 Global.asax 中的 Application_BeginRequest() 之类的东西中使用它,那么 99.9% 的情况下它会很好,但 0.1% 的情况下您可能会得到除您自己服务器的主机名之外的其他内容。

      我不久前发现的一个很好的例子。我的服务器往往会不时访问http://proxyjudge1.proxyfire.net/fastenv。 Application_BeginRequest() 很乐意处理此请求,因此如果您在发出此请求时调用 Request.Url.Host,您将返回 proxyjudge1.proxyfire.net。你们中的一些人可能会想“不,”但值得注意,因为这是一个很难注意到的错误,因为它只发生了 0.1% 的时间:P

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

      【讨论】:

      • 完全一样。我的域现在在 web.config 中。
      • 认为 不过我明白 - 为什么您的服务器会遇到 proxyfire?那是你的网站吗?但是,总体而言,这是有道理的——在特定于应用程序的事件期间使用特定于请求的对象可能效果不佳。在特定于请求的事件中是否存在危险,例如页面生命周期事件(Page.LoadCompleted 等)?
      • 我没有仔细调查为什么它会解析为 proxyfire。它当然不是我的网站,但它确实向我表明 Current.Request.Url 不是 100% 可靠的。经过大量研究后,我还发现动态确定主机名并不容易,因为多个 NIC 卡、IP 和域名解析到同一个 IP。至于你的另一个问题,马特,我不确定你的意思:(
      • 所以这只发生在 Application_BeginRequest 中?除非您可能没有设置主机标头,否则我看不出 IIS 是如何将此请求发送到您的应用程序的?
      • @Thirlan - 我正在尝试调试一个听起来与此类似的问题。我正在尝试使用 Request.Url.Host 获取子域,并且“通常”效果很好,但并非总是如此。真的有这个吗?喜欢请求中可能正确的其他内容吗?
      【解决方案7】:

      为什么不使用

      Request.Url.Authority

      它返回整个域和端口。

      你还是需要弄清楚http还是https

      【讨论】:

      • 这也有效。要“计算”http 或 https,只需在其前面加上“//”即可。例如,它会读作 href="//@Request.Url.Authority..."
      【解决方案8】:
      Request.Url.GetLeftPart(UriPartial.Authority)
      

      这是包含的方案。

      【讨论】:

        【解决方案9】:

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

        【讨论】:

          【解决方案10】:

          简单方式(支持架构、域和端口):

          使用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
          

          【讨论】:

            【解决方案11】:

            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
            

            【讨论】:

              猜你喜欢
              • 2010-12-02
              • 2013-03-23
              • 2018-03-17
              • 2018-10-25
              • 2011-01-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多