Avoid inherited ELMAH errors in an ASP.NET subapplication - asp.net

I have a parent IIS application that uses ELMAH and a child ASP.NET application (virtual directory) that doesn't use ELMAH. When I try to browse my subapplication I get this error:
Could not load file or assembly 'Elmah' or one of its dependencies. The system cannot find the file specified.
Which is understandable as my child application's bin folder doesn't contain any ELMAH assemblies.
The problem probably is that the parent web.config file contains this:
<configSections>
<sectionGroup name="elmah">
<section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
<section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
<section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
<section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
</sectionGroup>
</configSections>
As far as I understand there is no way to stop <configSections> inheritance, see e.g. How to stop inheritance of <configSections>in Web.Config. Is there a way to run my ELMAH-free subapplication then?

You cannot keep your subapplication ELMAH-free because of the parent configuration. However - since I imagine you don't want to reference the assemblies from the parent - what you can do is tell your subapplication to look for assemblies in the parent bin folder with the probing configuration.
This way your subapplication doesn't need to know what assemblies exist for the parent, only that if an unknown assembly is needed it can be found in the parent folders
Edit: That's indeed a bummer. Clearing and removing configsections tags was considered too complex by Microsoft :
<clear /> and <remove /> were never implemented for configSections and sectionGroups because of the difficulty involved attempting to merge different definitions of the same section-handlers and section groups.
Hence the path workaround. You could also set up the applications so they are not related in terms of hierarchy, if this is critical

I have found that adding enableConfigurationOverride="false" to the application pool definition fixes this problem.
From the MSDN docs:
Optional Boolean attribute. When true, indicates that delegated settings in Web.config files will processed for applications within this application pool. When false, all settings in Web.config files will be ignored for this application pool.The default value is true.
There are two methods of doing this, where ChildApplicationName should be replaced with the value of your application pool name.
Method 1 (preferred/advised):
Execute the following command in appcmd in Administrator mode:
appcmd.exe set config -section:system.applicationHost/applicationPools /[name='ChildApplicationName'].enableConfigurationOverride:"False" /commit:apphost
Method 2:
The second involves directly editing the %windir%\System32\inetsrv\config\applicationHost.config file allows the application to effectively ignore the parent application. For various reasons, I don't advice doing this, but I leave this here for posterity.
In order to set this, do a search for your child application pool name. It should be under the xpath. /configuration/system.applicationHost/applicationPools.
<configuration>
<system.applicationHost>
<applicationPools>
...
<add name="ChildApplicationName" enableConfigurationOverride="false" />
...
<applicationPools>
<system.applicationHost>
<configuration>

Related

How to use ASP.NET 4.8 ConfigBuilders with system.serviceModel section of web.config

I have an ASP.NET 4.8 app that I am trying to integrate configuration builders into. I have installed the NuGet package Microsoft.Configuration.ConfigurationBuilders.Environment and added the required sections to Web.config (heavily truncated here).
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="configBuilders" type="System.Configuration.ConfigurationBuildersSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false" requirePermission="false"/>
</configSections>
<configBuilders>
<builders>
<add name="EnvironmentExpand" mode="Expand" type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.Environment" />
</builders>
</configBuilders>
<system.serviceModel configBuilders="EnvironmentExpand">
....
</system.serviceModel>
</configuration>
When I run the application I get an HTTP 500 response from every action, with the message Unrecognized attribute 'configBuilders'. Intellisense in Visual Studio also highlights configBuilders and says The configBuilders attribute is not allowed.
If I remove the configBuilders attribute from system.serviceModel the application runs correctly although of course none of the placeholders in that section are expanded.
If I remove the configBuilders attribute from system.serviceModel and add it to another section, for instance connectionStrings, the application runs and the placeholders in the connectionStrings section are replaced.
Clearly there's something different about the system.serviceModel section but I don't understand what or how I can work around it so that I can replace placeholders in there.
If you look at your machine.config, you'll see that system.serviceModel is a sectionGroup and not a section. ConfigurationBuilders only apply at the section level. WCF and ASP.Net for better or worse have their large configuration divided into multiple sections.

web.config transform for microsoft.identitymodel configsection

How does one go about transforming the audienceUris and federatedAuthentication elements in the microsoft.identitymodel configuration section using the standard visual studio web.config transforms?
For the development environment, we have all the subdomains postfixed with a '-dev' along with special localhost port numbers, for example: realm="https://client-dev.domain.com:444". Today the main web.config reflects this but ideally we would like to move this setting to Web.Debug.config and in the Web.Release.config we would like to specify the proper audience and realms sans the '-dev' postfix and the local port settings. However, attempting to put xdt:Transform="Replace" in the microsoft.identitymodel element inside the Web.Debug.Config results in this warning:
The 'http://schemas.microsoft.com/XML-Document-Transform:transform' attribute is not declared.
and of course runtime failures (not being able to find servicecertificate for example).
Here's the microsoft.identitymodel sections:
<configuration>
<configSections>
<section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<microsoft.identityModel>
<service>
<applicationService>
<claimTypeRequired>
<claimType type="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier" optional="false" />
<claimType type="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" optional="false" />
</claimTypeRequired>
</applicationService>
<serviceCertificate>
<certificateReference x509FindType="FindByThumbprint" findValue="NNNNNNNNNN" storeLocation="LocalMachine" storeName="My" />
</serviceCertificate>
<certificateValidation certificateValidationMode="None" />
<audienceUris>
<add value="https://url/" />
</audienceUris>
<federatedAuthentication>
<wsFederation passiveRedirectEnabled="true" issuer="https://url/" realm="https://url/" requireHttps="true" />
<cookieHandler requireSsl="true" />
</federatedAuthentication>
<issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<trustedIssuers>
<add thumbprint="NNNNNNNNNN" name="https://url/" />
</trustedIssuers>
</issuerNameRegistry>
</service>
</microsoft.identityModel>
<configuration>
Existing solutions that don't work:
1) Same issue was raised here but no proper response. The RemoveAll and Insert doesn't work:
Web config transform on microsoft.identityModel - 'http://schemas.microsoft.com/XML-Document-Transform' attribute is not declared
2) Also, tried to manipulate the namespace as suggested on this thread and this doesn't work either:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/9ededb66-3e34-4bba-8e20-a2cc6025f0f9
3) configSource looked promising but again does work when specified in the microsoft.identitymodel element.
I get:
Warning 1 The 'configSource' attribute is not declared.
http://blog.andreloker.de/post/2008/06/16/Keep-your-config-clean-with-external-config-files.aspx
Any help will be appreciated! Thanks.
After a lot of trial and error, I resorted to using XMLPreProcess by Loren Halvorson to auto-generate the correct Web.config from a TemplateWeb.config as part of the pre-Build event for each project.
Although I would have liked Visual Studio's attempt at this to work for developers, alas, time is of money and its time for me to move on. Needless to say, it's broken in the SQL Azure SDK as well because the transforms only occured when you publish a site. In the latest Azure SDK, that is no longer the case and hence transforms stopped working as well. Oh joy!
Here's a link to the excellent tool, I think, a must-have for every ASP.NET developer:
http://xmlpreprocess.codeplex.com/

'System.Web.Extensions' trouble deploying .Net Framework 4 Website on IIS7

I am trying to deploy a .Net framework 4 website on IIS7 server. I have already changed the application-pool's target framework to .Net 4, but the app is still showing me the error:
"The configuration section 'system.web.extensions' cannot be read because it is missing a section declaration"
I am guessing that has something to do with the new feature of .Net4 that lets me have a compact Web config file. I think for some reason IIS7 is not happy with this.
What can I do to deploy this app successfully or do I have to scale back to v3.5? I am sure there is a solution out there.
Do you have any suggestions?
You can also get this very same error if you create a new website in IIS 7(.5) as the application pool it creates for the new site may still be set to 2.0, and as such, system.web.extensions is not valid in a 2.0 configuration file.
Simply go into IIS Manager, choose the application pools, select the one for your app, right-click, Advanced Settings and set .NET framework version to v4.
Module IIS Web Core
Notification BeginRequest
Handler Not yet determined
Error Code 0x80070032
Config Error The configuration section 'system.web.extensions' cannot be read because it is missing a section declaration
Config File \\web.config
The error is due to this system.web.extensions section added to the Web.config
<system.web.extensions>
<scripting>
<webServices>
<!-- Uncomment this line to customize maxJsonLength and add a custom converter
<jsonSerialization maxJsonLength="1024000">
-->
</webServices>
<scriptResourceHandler enableCompression="true" enableCaching="true"/>
</scripting>
</system.web.extensions>
For some reason adding that section, overrides the system.web.extensions group. The solution is to
Comment the code above if you don't need it.
Add the code below to the Web.config section group
..
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere" />
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
</sectionGroup>
</sectionGroup>
</sectionGroup>
I could solve this issue myself after some hunting around (happens!).
apparently has nothing to do with the way the config file is structured, it is the assembly for ASP.Net Ajax which is not deployed on my target server but might be present on my dev machine.
I deleted the entry from the web.config file and this issue was resolved, there were some other minor issues but nothing worth mentioning.
The deployment experience for IIS7+.Net Framework 4 wasn't too difficult and the added capabilities will going to be worth it.
I found the answer from Leo Tang post:
This issue not caused by the web.config migration. If you update you application to .Net Framework4.0, but assign this application to an application pool running under .Net Framework3.5 or previous version, you will encounter this error.
You can assign this application to an .Net Framework4.0 application pool in IIS to fix issue.
So, if you read the error The configuration section 'system.web.extensions' cannot be read because it is missing a section declaration it’s because the application you have deployed is running under an application pool configured to run under .NET 2.0 or 3.5 (DefaultAppPool? DefaultAppPool by default is set to .NET 2.0).
Perform the following steps:
Run IIS (exec 'inetmgr')
Select your application (probably 'Server\Sites\Default web site\Your application name' from the tree on the left panel)
Open your application settings (click 'Basic Settings' from 'Actions' the right panel) and look at the Application Pool.
Now choose the action that best fits your needs:
You can change the application pool for your application (button select in 'Application Edit' form, then choose 'ASP.NET v4-0 Classic'). This change will effect just this application
OR you can edit the application pool (probably Server\Application pools\DefaultAppPool rom the tree on the left) and set it to run under .NET Framevork v4.0 . Be careful: this change will effect every application under this Application Pool... is this what you want? maybe...
If "aspnet_regiis.exe -iru" don't help and you sure, that you try to launch site under .NET 4.0 App pool, it may be the problem in configuration inheritance of IIS 7.0. Web server reads machine.config of .NET 2.0.
Applying of hotfix KB958854 would solve the problem with configuration inheritance. I have successfully fixed my problem in this way.
It’s because you’ve deployed your application on to an IIS Server where the application’s AppPool is set to run under the DefaultAppPool. DefaultAppPool is automatically configured to run under .NET 2.0 rather than .NET 4.0. This means that the System.Web.Extensions stuff is unavailable to that version of the .NET Framework.
To change the Application Pool (AppPool) settings for your web application
1. Select the application directory
2. Under Actions, click Basic Settings…
3. Change the Application Pool to ASP.NET v4.0 (or another .NET 4.0 app pool) by clicking on the Select… button.
4. Click OK
Re-run your application and it should work.
Check this link for graphical demonstration.
I solved the issue by following below steps:
1. set application pool framework to 4.0
2. if point 1 wont work, then problem could be related to config inheritance.
Apply hotfix from http://support.microsoft.com/kb/958854
This should solve the issue.

Custom Configuration Sections

I am currently trying to implement a Custom Configuration Section in a project I am busy with and no matter what I try I keep getting the error below:
{"An error occurred creating the configuration section handler for pageAppearanceGroup/pageAppearance: Could not load type 'Samples.AspNet.PageAppearanceSection' from assembly 'System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. (E:\Three Nine Developments\lastfm\msdn\msdn\bin\Debug\Samples.Aspnet.vshost.exe.config line 6)"}
I have copied the code from this MSDN Artricle:
http://msdn.microsoft.com/en-us/library/2tw134k3.aspx
I still get the same error.
I have tried the all the advice/guide in the following articles but to no avail.
http://www.evanclosson.com/devlog/bettercustomerrorsinaspnetcustomconfigurationsection
Link
This must be something stupid that I am missing.
I am running Vista, could that be a problem? some obscure security setting?
<configuration>
<!-- Configuration section-handler declaration area. -->
<configSections>
<sectionGroup name="pageAppearanceGroup">
<section
name="pageAppearance"
type="Samples.AspNet.PageAppearanceSection"
allowLocation="true"
allowDefinition="Everywhere"
/>
</sectionGroup>
<!-- Other <section> and <sectionGroup> elements. -->
</configSections>
<!-- Configuration section settings area. -->
<pageAppearanceGroup>
<pageAppearance remoteOnly="true">
<font name="TimesNewRoman" size="18"/>
<color background="000000" foreground="FFFFFF"/>
</pageAppearance>
</pageAppearanceGroup>
</configuration>
My guess is that you've copied the code, but you have different assembly names. Posting the config will help.
I would also fully quality your type in the config (something that sample doesn't show). Something like...
<section name="MySection" type="My.Assembly.Type, My.Assembly" />
You should also check out Jon Rista's three-part series on .NET 2.0 configuration up on CodeProject.
Unraveling the mysteries of .NET 2.0 configuration
Decoding the mysteries of .NET 2.0 configuration
Cracking the mysteries of .NET 2.0 configuration
Highly recommended, well written and extremely helpful!
Marc
Please try with the following code:
<configSections>
<sectionGroup name="pageAppearanceGroup">
<section name="pageAppearance" type="Samples.AspNet.PageAppearanceSection,Samples.AspNet" allowLocation="true" allowDefinition="Everywhere" />
</sectionGroup> <!-- Other <section> and <sectionGroup> elements. -->
</configSections>
Please try with this
<configSections>
<sectionGroup name="pageAppearanceGroup">
<section name="pageAppearance"
type="Samples.AspNet.PageAppearanceSection,Samples.AspNet"
allowLocation="true"
allowDefinition="Everywhere" />
</sectionGroup>
<!-- Other <section> and <sectionGroup> elements. -->
</configSections>
Thanks,
Vedi
So it turns out that when you create a project in Visual Studio, it automatically defines a root namespace (the name of the project by default) for the project. Thus you must include that root namespace in the section type as well as any custom namespaces you defined within your settings class.
For example, in the case of the original poster a working configuration for them may have looked something like this:
<section name="MySection" type="ROOT_NAMESPACE.Samples.AspNet.PageAppearanceSection, NAME_OF_ASSEMBLY" />
Where ROOT_NAMESPACE and NAME_OF_ASSEMBLY are defined in the project properties as shown in this snapshot of my project.
In my particular case, I did not explicitly define namespaces in my project. Thus my section configuration setting just had the root namespace, the name of the settings class, and the name of the assembly, as such;
<section name="programSettings" type="ShipmentImport.ProgramSettings, ShipmentImport" />
I know its a couple years late, but I hope it keeps somebody else from spending hours on this like I did.

Using ASPNet_Regiis to encrypt custom configuration section - can you do it?

I have a web application with a custom configuration section. That section contains information I'ld like to encrypt (was hoping to use ASPNet_RegIIS rather than do it myself).
Web.Config:
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<configSections>
<section name="MyCustomSection"
type="MyNamespace.MyCustomSectionHandler, MyAssembly"/>
</configSections>
<configProtectedData>
<providers>
<clear />
<add name="DataProtectionConfigurationProvider"
type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=MSIL"
keyContainerName="MyKeyContainer"
useMachineContainer="true" />
</providers>
</configProtectedData>
<MyCustomSection>
<blah name="blah1">
<blahChild name="blah1Child1" />
</blah>
</MyCustomSection>
The configuration handler works great before trying to encrypt it. When I try to encrypt it with:
aspnet_regiis -pef "MyCustomSection"
c:\inetpub\wwwroot\MyWebsite -prov
DataProtectionConfigurationProvider
I get an error:
Encrypting configuration section... An
error occurred creating the
configuration section handler for
MyCustomSection: Could not load file
or assembly 'MyAssembly' or one of its
dependencies. The system cannot find
the file specified.
(c:\inetpub\wwwroot\MyWebsite\web.config
line 5)
I have tried with/without the provider configured. With/without section groups. With/Without having started the website before hand. I've tried temporarily putting my assembly in the GAC for the registration. I also tried my log4net section just to try something that wasn't mine, with no luck. I've run the command prompt as Administrator. Any ideas? Or can ASPNet_RegIIS just not be used for custom sections?
One final shot after viewing MSDN was changing my handler to inherit from ConfigurationSection rather than implementing IConfigurationSectionHandler since it was technically deprecated in 2.0 (hoping it was something regarding aspnet_regiis version). No luck there either.
Any ideas let me know. Thanks!
aspnet_regiis must be able to bind the assembly. The normal .net binding rules apply.
I get around this by creating directory called aspnet_regiis_bin in the same directory as aspnet_regiis.exe and an aspnet_regiis.exe.config file with aspnet_regiis_bin as a private path like this:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="aspnet_regiis_bin"/>
</assemblyBinding>
</runtime>
</configuration>
I then copy the assemblies that define the custom configuration sections into aspnet_regiis_bin so that aspnet_regiis can find them.
This procedure doesn't require the assemblies to be strong named or in the GAC but does require messing around in the framework directories.
I am using a workaround whereby I temporarly comment out the contents of the configSections element:
<configSection>
<!--
<section name="CustomSection" type="" />
-->
</configSection>
You can then run the encryption using aspnet_regiis -pef as usual. After this has run just uncomment the section and your site is ready to run.
This is a total hack, but I'm not sure that there's another way to do it without strongly naming the assembly that defines your custom section and GACifying it (although you mentioned that didn't work, either, and I'm not sure why it wouldn't). Since aspnet_regiis runs in the < drive >:\Windows\Microsoft.Net\Framework\< version > folder (in WinXP), you can copy the DLL that defines your config section into the relevant Framework\< version > folder, and then it should work.
For the record, I ended up with a little maintenance page to do this for me.
var currentConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~/");
// Unprotect
ConfigurationSection section = currentConfig.GetSection("MyCustomSection");
if (section.SectionInformation.IsProtected)
{
section.SectionInformation.UnprotectSection();
currentConfig.Save();
}
// Protect
if (!section.SectionInformation.IsProtected)
{
section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
currentConfig.Save();
}
Caveats: Your process will need write access to the config files being modified. You'll want some way to authorize who can run this. You'll generally restart the website when you Save.
The answer that is shown as correct is correct. I wanted to add a comment but could not because this is too long of a comment (sample config entries).
The section name should use the full name of the assemblies. A runtime assembly qualification does not work with aspnet_regiis.exe.
This WORKS:
<configSections>
<section name="securityConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Security.Configuration.SecuritySettings, Microsoft.Practices.EnterpriseLibrary.Security, Version=5.0.414.0, Culture=neutral, PublicKeyToken=9c844884b2afcb9e" />
</configSections>
But this DOESN'T WORK:
<configSections>
<section name="securityConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Security.Configuration.SecuritySettings, Microsoft.Practices.EnterpriseLibrary.Security" />
</configSections>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<qualifyAssembly partialName="Microsoft.Practices.EnterpriseLibrary.Security" fullName="Microsoft.Practices.EnterpriseLibrary.Security, Version=5.0.414.0, Culture=neutral, PublicKeyToken=9c844884b2afcb9e" />
</assemblyBinding>
</runtime>

Resources