【问题标题】:How to get full host name + port number in Application_Start of Global.aspx?如何在 Global.aspx 的 Application_Start 中获取完整的主机名 + 端口号?
【发布时间】:2011-05-13 16:44:45
【问题描述】:

我试过了

Uri uri = HttpContext.Current.Request.Url;
String host = uri.Scheme + Uri.SchemeDelimiter + uri.Host + ":" + uri.Port;

它在我的本地机器上运行良好,但是在发布到 IIS7 时,出现异常提示

System.Web.HttpException: Request is not available in this context

有人知道如何实现吗?

【问题讨论】:

标签: c# asp.net url request hostname


【解决方案1】:

当您的 Web 应用程序启动时,不会处理任何 HTTP 请求。

您可能希望处理定义请求上下文可用的 Application_BeginRequest(Object Sender, EventArgs e) 方法。

编辑:这是一个代码示例,灵感来自 Michael Shimmins 链接到的 Mike Volodarsky 的博客:

    void Application_BeginRequest(Object source, EventArgs e)
    {
        HttpApplication app = (HttpApplication)source;
        var host = FirstRequestInitialisation.Initialise(app.Context);
    }

    static class FirstRequestInitialisation
    {
        private static string host = null;
        private static Object s_lock = new Object();

        // Initialise only on the first request
        public static string Initialise(HttpContext context)
        {
            if (string.IsNullOrEmpty(host))
            {
                lock (s_lock)
                {
                    if (string.IsNullOrEmpty(host))
                    {
                        var uri = context.Request.Url;
                        host = uri.GetLeftPart(UriPartial.Authority);
                    }
                }
            }

            return host;
        }
    }

【讨论】:

  • 不应该是Uri uri = context.Request.Url; 也不能把下一行简化成uri.GetLeftPart(UriPartial.Authority);
  • 这也应该是一个静态类,不需要初始化host。
  • 那么在第一个 HTTP 请求到达之前真的没有办法获取端口号吗?
  • 其实没有。一个 ASP.NET 网站可以有多个绑定,它可以在多个主机和多个端口号下运行(例如网站的安全和非安全版本)。您只有一个正在运行的 Web 应用程序实例,传入的请求包含有关发起请求的主机的信息。 Web 应用程序只知道它是一个应用程序,它没有关于它在哪个主机下运行的真实上下文。如果您的应用程序有两个绑定,一个用于端口 80,一个用于端口 8080,您想要哪一个?你不知道,这就是为什么你要在每个请求的基础上使用它。
  • 这是一个非常优雅的解决方案。我发现需要在应用程序启动中获取“基本”域并在 JIT 应用程序时使用它。我最终将我的逻辑转移到 Begin_Request 中。 Application_Start 现在为空,而 Begin_Request 包含逻辑和对域是否为空或空的简单检查。
【解决方案2】:

接受的答案很好,但在大多数情况下(如果第一个请求是 HTTP 请求)您最好使用 Session_Start 事件,每个用户每 20 分钟左右调用一次(不确定多久会话有效)。 Application_BeginRequest 将在每个请求时触发。

public void Session_Start(Object source, EventArgs e)
{
   //Request / Request.Url is available here :)
}

【讨论】:

    【解决方案3】:

    只是回答这个问题,如果有人决定实际搜索这个主题......

    这适用于应用程序以任何模式启动...

    typeof(HttpContext).GetField("_request", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(HttpContext.Current)
    

    【讨论】:

    • 请注意该字段是非公开的(即私有的)。您应该非常小心地使用未记录的功能和字段,因为它们可能会在没有进一步信息的情况下发生变化。
    • HttpContext.Current.Request有什么区别???我看到了同样的结果
    猜你喜欢
    • 1970-01-01
    • 2016-09-02
    • 2016-02-09
    • 2014-07-28
    • 2011-02-05
    • 2014-05-18
    • 2016-05-24
    • 1970-01-01
    • 2021-02-20
    相关资源
    最近更新 更多