2017-03-09 1 views
0

OK, ça va, en postant ma toute première question SO après des heures de googling. Soyez doux s'il vous plaît :)Accès au runtime à la section web.config system.webServer/webSocket

Question: Toutes les idées comment passer l'erreur: « [System.Configuration.ConfigurationProperty] » est inaccessible en raison de son niveau de protection », lors d'une tentative de modifier web.config system.webServer/section webSocket en C#?

Contexte & ce que j'ai essayé: J'ai une application Web ASP.NET écrit en C# qui utilise Microsoft SignalR pour serveur < -> appels de fonction client. SignalR utilise le protocole Websocket lorsque cela est possible et retombe sur d'autres méthodes de transport lorsqu'il n'est pas disponible.

J'ai cette entrée dans mon web.config, dans la section system.webServer:

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

qui permet d'utiliser ma demande WebSocket donc je besoin de cette ligne. Aussi, parce que mes utilisateurs fonctionnent souvent dans des conditions de réseau difficiles, j'ai ajouté un pingInterval plutôt court. Cela fonctionne très bien, pas de problème.

Il est bien connu que Windows 2008 R2/IIS 7.5 (et versions inférieures) ne prend pas en charge WebSocket. Cependant, parfois, j'ai besoin de lancer mon application sur une ancienne version de Windows Server. Dans ce cas, j'ai besoin de supprimer manuellement la ligne ci-dessus, pour éviter de mauvaises erreurs IIS sur la configuration Web.config incorrecte. Cela fonctionne également très bien, mais je n'aime pas le travail supplémentaire d'avoir à supprimer cette ligne en fonction du serveur sur lequel je cours. J'ai donc ajouté du code dans mon Global.asax pour détecter la version du système d'exploitation et des services Internet, pour savoir si WebSocket est supporté ou non. Suivant Je souhaite ajouter ou supprimer de manière dynamique cette ligne de configuration WebSocket à l'exécution (Je suis d'accord avec le redémarrage de mon domaine d'application en cas de modification). Je dois faire cela entièrement par programme dans mon application, et en n'ayant pas besoin de changer quoi que ce soit sur IIS ou OS niveau.

J'ai regardé des articles tels que this one et this from MS et aussi beaucoup SO messages qui viennent très près de mon problème, comme this here et this regarding the actual error I get. Ceci est le plus proche que je peux obtenir en ce moment et je ne sais pas comment passer l'erreur:

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... 

Je suis très ouvert à d'autres suggestions sur la façon de contourner cela. En attendant, je vais continuer à googler ...

EDIT: oublié de mentionner que je suis sur 4.5 .NET

+0

Eh bien, j'ai réussi à résoudre cela par moi-même après tout. J'ai mis à jour le message original avec la partie "Solution". – tnurmi

+0

Vous devriez poster la solution comme réponse :) –

+1

Merci! J'ai modifié mon article d'origine, supprimé la partie "résolue" de là et l'ai ajoutée comme réponse, et l'ai également marquée comme réponse acceptée. Et il me semble que je suis juste en train de bavarder ici pour moi ... :) – tnurmi

Répondre

2

RESOLU! Eh bien après quelques heures d'essai, je l'ai eu à travailler exactement comme je le voulais. Voici le morceau de code pertinent, pas peut-être le plus beau code, mais cela fonctionne:

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