运行时访问 web.config system.webServer/webSocket 部分

Runtime access to web.config system.webServer/webSocket section

好的,在谷歌搜索数小时后发布我的第一个 SO 问题。请温柔点:)

问题: 尝试修改 web.config system.webServer/webSocket C# 中的部分?

背景和我的尝试: 我有一个用 C# 编写的 ASP.NET Web 应用程序,它利用 Microsoft SignalR 进行服务器 <-> 客户端函数调用。 SignalR 尽可能使用 Websocket 协议,当它不可用时回退到其他传输方法。

我的 web.config 中有这个条目,在 system.webServer 部分:

<webSocket enabled="true" pingInterval="00:00:10" />

这使我的应用程序能够使用 WebSocket,所以我需要这一行。此外,因为我的用户经常在困难的网络条件下操作,所以我添加了一个相当短的 pingInterval。这很好用,没问题。

众所周知Windows 2008 R2 / IIS 7.5(及更低版本)不支持WebSocket。但是有时我需要 运行 我的应用程序在较旧的 Windows 服务器版本上。在那种情况下,我需要手动删除上面显示的行,以避免因 Web.config 配置不正确而导致的令人讨厌的 IIS 错误。这也很好用,但我不喜欢根据我运行正在使用的服务器删除此行的额外工作。

所以,我在 Global.asax 中添加了代码来检测 OS 和 IIS 版本,以了解是否支持 WebSocket。接下来 我想在 运行time 动态添加或删除该 WebSocket 配置行(我可以在更改后重新启动我的应用程序域)。 我需要在我的应用程序中完全以编程方式执行此操作,并且不需要更改 IIS 或 OS 级别 .

上的任何内容

我看过 this one and this from MS and also many SO posts that come very close to my problem, like and this regarding the actual error I get 等文章。这是我目前能得到的最接近的,我不知道如何克服错误:

System.Configuration.Configuration webConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("/MICC");
//At this point I can see that webConfig.FilePath is pointing to correct Web.config file
System.Configuration.ConfigurationElement webSocketElement = webConfig.GetSection("system.webServer/webSocket");
if (webSocketElement == null)
{
  //Not sure how to initialize a new ConfigurationElement, if GetSection() returned null
}
else
{
  //Attempting to change values, but following two lines gives me:
  //[System.Configuration.ConfigurationProperty]' is inaccessible due to its protection level

  webSocketElement["enabled"] = true;
  webSocketElement["pingInterval"] = TimeSpan.Parse("00:00:99"); //Test value
}
webConfig.Save(); //Never getting this far...

我也非常愿意接受有关如何解决此问题的任何其他建议。 同时我会继续谷歌搜索...

编辑: 忘了说我在 .NET 4.5

已解决! 经过几个小时的尝试,我让它完全按照我的需要工作。这是相关的代码,也许不是最漂亮的代码,但它可以工作:

public static bool enableWebSocket()
{
    System.Configuration.Configuration webConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("/my-apps-name-under-my-iis-site");
    System.Configuration.ConfigurationSection webServerSection = webConfig.GetSection("system.webServer");

    //This was the "magic" discovery. Just get the whole bunch as raw XML for manual editing:                
    XmlDocument webServerXml = new XmlDocument();
    webServerXml.LoadXml(webServerSection.SectionInformation.GetRawXml());
    //Check if the line is already there:
    XmlNodeList nodes = webServerXml.GetElementsByTagName("webSocket");
    if (nodes.Count > 0)
    {
      return false; //Already there, do nothing...
    }
    else //Node not yet found, so let's add it:
    {
        //Create a new XmlNode with the needed attributes:
        XmlNode webSocket = webServerXml.CreateNode(XmlNodeType.Element, "webSocket", null);
        XmlAttribute attr = webServerXml.CreateAttribute("enabled");
        attr.Value = "true";
        webSocket.Attributes.Append(attr);
        attr = webServerXml.CreateAttribute("pingInterval");
        attr.Value = "00:00:10";
        webSocket.Attributes.Append(attr);

        //Append original <system.webServer> section with the new XmlNode:
        webServerXml.DocumentElement.AppendChild(webSocket);

        //And finally store the modified <system.webServer> section in Web.config:    
        webServerSection.SectionInformation.SetRawXml(webServerXml.OuterXml);
        webConfig.Save();
        return true; //All done!
    }
}