Thursday, 8 April 2010

SOLVED: Breaking parent web.config dependencies in sub applications

This article explains how to implement a sub application such as a blog in your website without experiencing dependency issues. A common problem that developers experience is when their sub applications accidentally inherit requirements of the parent website. This is actually by design but read on if this is causing problems in your site.

Scenario

This problem has caught me out a couple of times so far but usually with enough of a gap between occurrences that it had become just a fuzzy memory. Hopefully by writing this article it will solidify it in my head and also help out other developers experiencing this for the first time.

Unfortunately this problem doesn't have a specific phrase or keyword that will make it easy for developers to find this solution in search engines. I want to rephrase this a couple of ways to hopefully capture the terms a developer might use when trying to solve this problem:

  • My blog, forum, gallery is requiring dlls from my parent website
  • When I install [software] in my site it tries to load assemblies from the main website
  • How do I stop my sub websites from needing the main sites bin folder
  • Could not load file or assembly 'assembly name' or one of its dependencies. The system cannot find the file specified.

That should do it but any further phrasings (such as the search term you arrived here through) are welcome in the comments section.

The problem occurs when you install a third party application as an application within an existing web site. I have had this occur when I have done the installation manually and also when I have used the Web PI.

This could encompass any of the applications out there such as forums, blogs, galleries, shopping carts or anything that runs as its own application.

The actual error message will most likely take the format of:

"Could not load file or assembly 'assembly name' or one of its dependencies. The system cannot find the file specified."

Solution

The reason this is occurring is actually by design. The settings inside the main web.config will cascade downwards and all other config files will inherit the settings. If they have settings of their own they will override the parent. In fact even the root web.config is being merged with a server wide file called machine.config.

So what's happening is the references to the assemblies in your main \bin\ folder are being passed down to the sub application and when it looks in its own bin folder it finds they aren't their and throws an error.

The obvious solution is to block these settings being inherited by a lower config file. This is achieved by wrapping the <system.web> section in the following tag:

 <location path="." inheritInChildApplications="false">
   <system.web>
     <!-- ... -->
   </system.web>
 </location>

If you have used DOS or FTP then you will probably realise that in the path="." the dot means current folder. This applies the inheritChildApplications="false" to all applications below the current folder. If you have a virtual folder setup in IIS that is at different physical location this is still counted as below the current application if its virtual url is below the current one.

Running IIS7 or above?

The newer versions of IIS have moved their configuration settings to a new section. If you have a web.config that is for IIS7 then you will need to also wrap <system.webServer> which is further down.

<location path="." inheritInChildApplications="false"> 
  <system.webServer>
    <!-- ... -->
  </system.webServer>
</location>

You can have more than one <location> block in a web.config so it would be fine to do this to wrap around both sections.

IIS7 and validateIntegratedModeConfiguration

If you were previously relying on the <validation validateIntegratedModeConfiguration="false" /> tag for the correct functioning of your site you might need to follow this technique to avoid a 502.22 Internal Server Error.

Only available in 2.0

Please note that if you're working with an asp.net 1.1 application you will not be able to put this tag in to block child applications as it was only introduced in 2.0. In this case your only real option as far as I know is to add <remove> elements into the child applications to cancel out each of the assemblies loaded in the asp.net 1.1 app. This is not a pretty solution because it tightly couples the two projects together however if you are in this situation and cannot upgrade the 1.1 app to 2.0 then it might be your only way out.

Restrictions with this technique

Please note that you cannot simply wrap the ENTIRE web.config in this tag as the root node must be the <configuration> tag.

There are also certain sections you cannot wrap the <location> tag around such as the <configSections> tag.

You can use more than one <location> tag to exclude various sections. Alternatively you can reorder portions of the web.config so that a single <location> can span multiple sections.

Incompatibilities with the WSAT

If you use the Web Site Administration Tool to configure your directory security you may have problems with the web.configs that the tool places in subdirectories. If this is the case then you can move the contents of the lower web.configs up into the main config and wrap them in a <location path="path to file or folder"> tag.

Breaks local debugging

I have noticed that while this works great for allowing an application and a sub application to work in harmony on the server it can cause confusion when you try to use it on your local dev server. In doing research into this issue it turns out that this is a known bug which has been in the official to do list for quite a while but as it doesn't affect many users hasn't been resolved yet. You can read about and vote for this bug on Microsoft Connect at:

The scenario is that if you place a <compilation debug="true"> element within a <location path="." inheritInChildApplications="false"> element the debug="true" will not be understood.

This means that when you press the play button to start debugging it will compile, launch the site and then immediately close the debug session. Your website will load up and you will be able to use it as normal but if you look at it in visual studio you will see the debug play button is available and the app is not considered to be currently being debugged.

It may also mean that your app will simply fail to compile locally (but works fine on the server).

There is a work around for this; by commenting the <location> element out and restarting the debug process local debugging will being working correctly again.

As of the current version there is no way to automate setting this tag between local and production environments although it may be possible with the new web.config transformations in the upcoming .net 4 release.

19 comments:

Martin said...

Thanks, your article was very helpful

Olav said...

Thaks, I have been looking for this page!

kevin said...

It also appears that using the location tag breaks web.config transformations in VS2010

Naji Abdelraziq said...

Love You Man

Naji Abdelraziq said...

Thanks man... very helpful article...

Ullas said...

Cheers man, this saved my day..

Anonymous said...

What is the solution for a reverse problem. How to isolate all parent config setting from a child application. i.e Child app is totally a separate application or website.

rtpHarry said...

@Anonymous - I think the solution for the reverse of this is to set that folder as an application in IIS but this is just off the top of my head.

Pawel said...

This is what I needed to fix inheritance in IIS 7 no wonder it wasnt working ! Now my Parent runs ASP4 and the child apps run ASP2 no problems. I spent 4 hours looking for this solution. Thank You!!

James Grigley said...

This allowed me to run a 2.0 app inside of a 4.0 site thank you!

Unknown said...

Does this go in the parent application or the child application?

Endless Ending said...

Appreciate your work. Thanks it solved the problem i learnt a new thing. your way of explaining things are really great. anyone even the most dumb programmer/developer could solve and learn easily.

Jason said...

This works great if you want to stop inheritance in all of your sub folders, but what if you want to stop inheritance in only ONE specific folder?

Anonymous said...

Before I read this article I was thinking of killing myself. Or just a career change. Whatever.

Thank you for solving this heartache! ("iis url rewrite prevent inherit" were my search terms btw)

Jack Kerwin said...

Very insightful and helpful content. I'm using a CMS while maintaining sub-applications within its web site. This article helped me clear at least this first hurdle! Thanks!!

Raphael Ribeiro said...

i did this, and i got no errors, but my imgs, style and scritps were gone, can u help me to solve this?

Anonymous said...

Thanks

Anonymous said...

ThANKS A LOT saved my precious time ....

One more thing I would like to add when you add inheritInChildApplications tag in web.config it might shows you message "The inheritInChildApplications attribute is not allowed." Just Ignore the message.

once again thanks a lot.

Afshar Mohebbi said...

Hi,
It helped me a lot. I was using Orchard CMS as parent and BlogEngine.NET as child. Unfortunately after hours of challenge because of sectionGroup restriction I forced to switch to IIS URL Rewrite.

I wrote about my experience in Persian here: http://bit.ly/1lxu8Nc