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

时间:2017-03-09 09:18:17

标签: c# iis websocket web-config asp.net-4.5

好了,好吧,经过数小时的谷歌搜索,发布了我的第一个问题。请温柔:)

问题:任何想法如何克服错误:" [System.Configuration.ConfigurationProperty]'在尝试修改C#中的web.config system.webServer / webSocket部分时,由于其保护级别"而无法访问?

背景&我尝试了什么: 我有一个用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 Server版本上运行我的应用程序。在这种情况下,我需要手动删除上面显示的行,以避免有关不正确的Web.config配置的令人讨厌的IIS错误。这也很好,但我不喜欢根据我正在运行的服务器而删除此行的额外工作。

因此,我在Global.asax中添加了代码以检测操作系统和IIS版本,以了解是否支持WebSocket。下一步我想在运行时动态添加或删除该WebSocket配置行(我的appdomain在更改时重新启动)。 我需要在我的应用程序中以编程方式完成此操作,并且无需在IIS或操作系统级别上更改任何内容

我查看了this onethis from MS等文章以及与我的问题非常接近的许多SO帖子,例如this herethis 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上提及我

1 个答案:

答案 0 :(得分:2)

<强>解决! 经过几个小时的尝试后,我完全按照我的需要开始工作。这是相关的代码片段,可能不是最漂亮的代码,但它有效:

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!
    }
}