【问题标题】:Is it possible to get the host in Application _Start?是否可以在 Application _Start 中获取主机?
【发布时间】:2015-03-24 19:35:46
【问题描述】:

我有一个绑定了多个主机名的网站。是否可以在 Application_Start() 中找出正在使用的主机?

我知道我此时没有请求,所以我认为可能没有,但是我知道访问应用程序的每个主机都将在新的应用程序池下运行。所以只是想知道我是否可以在 IIS 中查询任何可以告诉我当前应用程序池正在使用什么主机名的东西?

【问题讨论】:

  • 你想要完成什么?
  • @JohnSaunders 在代码库方面我有一个应用程序,但我有多个客户在不同的主机名下使用这个应用程序。当一个请求进来时,我会得到他们的配置信息。这没什么大不了的,因为它被放入一个静态变量中,如果它被设置,我不会再次设置它。但我只是好奇是否有办法在应用程序启动时执行此操作,因为理论上我应该拥有所需的所有信息。

标签: c# asp.net iis host


【解决方案1】:

是否可以在 Application_Start() 中找出正在使用的主机?

不,不是。

根据您的 cmets,我想说您所追求的持久性机制是服务器端缓存选项之一(System.Runtime.CachingSystem.Web.Caching)。

System.Runtime.Caching 是这两种技术中较新的一种,它提供了一个抽象的ObjectCache 类型,可以潜在地扩展为基于文件的类型。或者,有一个内置的MemoryCache 类型。

与使用静态方法不同,缓存将根据超时(固定或滚动)为所有用户(和所有域)保持状态,并且可能具有缓存依赖性,这将导致缓存立即失效。一般的想法是在缓存过期后从存储(文件或数据库)重新加载数据。缓存保护存储免受每个请求的命中 - 仅在达到超时或缓存失效后才命中存储。

您可以在第一次访问缓存时填充缓存(大概是在请求已经填充之后,而不是在Application_Start 事件中),并使用域名作为缓存键的一部分(或全部)用于查找数据。

public DataType GetData(string domainName)
{
    // Use the domain name as the key (or part of the key)
    var key = domainName;

    // Retrieve the data from the cache (System.Web.Caching shown)
    DataType data = HttpContext.Current.Cache[key];
    if (data == null)
    {
        // If the cached item is missing, retrieve it from the source
        data = GetDataFromDataSource();

        // Populate the cache, so the next request will use cached data

        // Note that the 3rd parameter can be used to specify a 
        // dependency on a file or database table so if it is updated, 
        // the cache is invalidated
        HttpContext.Current.Cache.Insert(
            key, 
            data, 
            null, 
            System.Web.Caching.Cache.NoAbsoluteExpiration, 
            TimeSpan.FromMinutes(10), 
            System.Web.Caching.CacheItemPriority.NotRemovable);
    }

    return data;
}

// Usage
var data = GetData(HttpContext.Current.Request.Url.DnsSafeHost);

如果它很重要,您可以使用类似于Micro Caching in ASP.NET 的锁定策略(或只使用该解决方案批发),以便在缓存过期时数据源不会收到多个请求。

此外,您可以指定项目为“不可移除​​”,这将使它们在应用程序池重新启动时仍然存在。

更多信息:http://bartwullems.blogspot.com/2011/02/caching-in-net-4.html

【讨论】:

  • 谢谢,这基本上就是我正在做的。我有一个基本页面,可以获取第一个请求的数据,但没有后续请求的数据。除了我缓存的数据会很少更改(如果有的话),甚至不值得失效,所以这就是我只使用静态变量的原因。
【解决方案2】:

嗯,IIS 不是域权限,因此只有在您手动保持本地设置和 DNS 设置同步时,它才能读取 IIS 设置。但是有一种方法可以读取 IIS 绑定。因此,如果您在 IIS 配置中使用主机头名称,您可以有效地读取域名。

// Get the current Site Name
var siteName = HostingEnvironment.SiteName;

// Get the sites section from the AppPool.config
var sitesSection = WebConfigurationManager.GetSection(null, null, "system.applicationHost/sites");

var site = sitesSection.GetCollection().Where(x => string.Equals((string)x["name"], siteName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

if (site != null)
{
    foreach (var iisBinding in site.GetCollection("bindings"))
    {
        var protocol = iisBinding["protocol"] as string;
        var bindingInfo = iisBinding["bindingInformation"] as string;

        string[] parts = bindingInfo.Split(':');
        if (parts.Length == 3)
        {
            //string ip = parts[0]; // May be "*" or the actual IP
            //string port = parts[1]; // Always a port number (even if default port)
            string hostHeader = parts[2]; // May be a host header or "". This will only be the domain name if you keep it in sync with the DNS.

            // Use the hostHeader as the domain name
        }
    }
}

为此,您需要设置对Microsoft.Web.Administration.dll 的引用,即available via NuGet

参考:http://blogs.msdn.com/b/carlosag/archive/2011/01/21/get-iis-bindings-at-runtime-without-being-an-administrator.aspx

【讨论】:

  • 好的,这让我得到了绑定列表...但是我怎么知道调用代码与哪一个相关联?
  • 好点。我假设您将每个应用程序托管为不同的 IIS 站点,因此只需使用 StartsWith 或 RegEx 找到正确的绑定字符串即可。但是,如果您在同一个站点中托管所有域,这将不起作用。从那以后,我为您的问题提出了一个更好的解决方案并添加了另一个答案,但这仍然可能对某人有所帮助。
猜你喜欢
  • 1970-01-01
  • 2015-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-20
  • 1970-01-01
  • 2013-12-20
  • 1970-01-01
相关资源
最近更新 更多