Tuesday, 16 December 2014

Avoid Web.Config Inheritance in Child Web Application by using location inheritInChildApplications = false

With shared hosting platforms like: HostGator, GoDaddy, Dreamhost to name a few, you can easily pickup some entry level Windows Plesk Hosting with all the ASP.NET trimmings quite cheaply! If you're an avid developer with a hand in all the pies, you probably have at least 5 or more web apps and/or web services you want to host all in the same shared hosting space!
If this IS your scenario, beware that entry level shared hosting plans have ONE APP POOL for ALL of your apps! See my post on Application Pools and Web Applications for more information.

Why may I need to do this?
If you have a web application, for example, sitting in your root directory and another web application/service sitting in a sub folder, then by default, this child web app will inherit the Web.Config settings of the root application.
If your root application is .NET 4.5 and your sub-apps are .NET 2.0, then you may already be seeing a few fancy errors! This is just one of many reasons why we need to prevent this. This post outlines TWO methods to do this...

Method 1
You can prevent inheritance by utilizing the location tag's inheritInChildApplications attribute. You should put the location tag in the ROOT Web.Config and NOT the child app's Web.Config in our example. The path attribute of the location tag is set to a wildcard (.) to specify ANY child app location. You can set this to a path attribute to target a single app if you prefer by entering it's location. As good practice, you should wrap individual tags with the location tag (The location tag can appear more than once in the Web.Config file!). Do not wrap EVERYTHING in the Web.Config with the location tag.
Code Snippet
  1. <?xml version="1.0"?>
  2. <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  3. <!-- disable inheritance for the connectionStrings section -->
  4. <location path="." inheritInChildApplications="false">
  5.    <connectionStrings>
  6.    </connectionStrings>
  7. </location>
  9. <!-- leave inheritance enabled for appSettings -->
  10. <appSettings>
  11. </appSettings>
  13. <!-- disable inheritance for the system.web section -->
  14. <location path="." inheritInChildApplications="false">
  15.    <system.web>
  16.         <webParts>
  17.         </webParts>
  18.         <membership>
  19.         </membership>
  21.         <compilation>
  22.         </compilation>
  23.       </system.web>
  24.  </location>
  25. </configuration>
End of Code Snippet

Note: I included xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0" as an attribute of the configuration tag as inheritInChildApplications is defined in the .NET 2.0 schema. Setting this is good practise and will also remove the warning in Visual Studio about the inheritInChildApplications attribute not being recognized.
WARNING!!! There is no good way of disabling inheritance of the configSections tag (As configSections must appear as the first tag in the Web.Config!). Microsoft issued a statement stating that it would be too complex to handle this appropriately using their given development methods. Simply, make sure that your sectiongroup name's don't clash with child apps. You can simply rename one of them if they do share the same name. Easy fix!

Method 2
You can also prevent inheritance by using clear and/or remove tags in the child's Web.Config to clear our any inherited values defined in the root Web.Config.
This is an example of a child app's Web.Config. It clears our any inherited connection strings defined by the root application. You then define the child app's connection strings BELOW the clear attribute. Note: Depending upon the Web.Config tag involved, you may need a remove attribute rather than a clear.
Code Snippet
  1. <?xml version="1.0"?>
  2. <configuration>
  3.     <connectionStrings>
  4.         <clear/>
  5.         <!-- Child config's connection strings -->
  6.     </connectionStrings>
  7. </configuration>
End of Code Snippet

No comments: