Custom Configuration Sections - asp.net

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.

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.

Is the web.config/app.config element configSections deprecated in DotNet4.5?

I have an old application in ASP.Net (3.5) that needs upgrading, however, after updating to 4.5, a configSections element in the web.config file is not recognized and the app fails to load. Did something change here?
the following used to work...
<configuration>
<configSections>
<section name="paypal" type="PayPal.SDKConfigHandler, PayPal" />
</configSections>
<!-- PayPal SDK settings -->
<paypal>
<settings>
<add name="mode" value="sandbox"/>
<add name="clientId" value="YOUR APPLICATION CLIENT ID"/>
<add name="clientSecret" value="YOUR APPLICATION CLIENT SECRET"/>
</settings>
</paypal>
</configuration>
but no joy
HTTP Error 500.19 - Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.
Config Source:
22:
23: <configSections>
24: <section name="paypal" type="PayPal.SDKConfigHandler, PayPal" />
I figured it out. It had nothing to do with permissions, IISExpress, or anything else, but only the position in the section. I moved element to just under the element and there's no error anymore. Go figure.
<configuration>
<configSections>
<section name="paypal" type="PayPal.SDKConfigHandler, PayPal" />
</configSections>
...
I've written my own XML parsers in the past that read the entire file and are not dependent on the order of the elements (just so long as it follows the structure & required elements are present). I incorrectly assumed that order does not matter in the web.config file. Good to know (probably save lots of coders headaches in the future).

Avoid inherited ELMAH errors in an ASP.NET subapplication

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>

using connectionstring from web.config instead of app.config

I have a class library project in which I've added a dataset which talks with sql server. The output of this project is to be consumed from a web application project. So I intend to put my connection string in the web application project.
Did a couple of things. In order to make my adapter use a different connection string, I had come across this. But I finally found doing the following convenient:
Dim adapter as New MyReqeustTableAdapter()
adapter.Connection.ConnectionString = sMyConnectionString
Then I tried taking the connection string from my configuration (app.config) to kind of simulate . I added a section manually with key "myconstr". My ideas was to do something like:
sMyConnectionString = ConfigurationManager.ConnectionString("myconstr").ConnectionString
But my intellisense couldn't not detect ConfigurationManager. So had to add the appropriate reference to the project.
Next I added a connection string via the settings designer for the web application project. I gave the above key for referencing it. However the above statment seems to throw a null reference exception.
Suppose you have created a class library. In it you've defined a Settings property which goes like:
Properties.Settings.Default.ProjectName
Visual Studio might auto generate some configuration for you as follows:
(app.config)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="MyDllProject.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<MyDllProject.Properties.Settings>
<setting name="ProjectName" serializeAs="String">
<value>MyDllproject</value>
</setting>
</MyDllProject.Properties.Settings>
</applicationSettings>
</configuration>
Now say you add this assembly to an project. And you access its settings, you'd most probably get MyDllproject as it value. This is in spite of adding any configuration. Why? Because when the assembly was generated it was kind of written into it. And the code written is such that in the absence of a configuration override use what was defined in the app.config at the time of generation.
Now in your target project, you simply add the necessary sections in the configuration file in the following pattern
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<!-- start: copied from app.config of class library -->
<section name="MyDllProject.Properties.Settings"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"
/>
<!-- end: copied from app.config of class library -->
<!-- other sections may follow -->
</sectionGroup>
</configSections>
<applicationSettings>
<!-- remember to maintain the same order as how it was defined in the sectionGroup -->
<!-- start: copied from app.config of class librarly -->
<MyDllProject.Properties.Settings>
<setting name="ProjectName" serializeAs="String">
<value>ConsoleProjectB</value>
</setting>
</MyDllProject.Properties.Settings>
<!-- end: copied from app.config of class library -->
<!-- other configurations settings may follow -->
</applicationSettings>
</configuration>
Thats it.
Here is a small project sample I've linked to for the same: http://sdrv.ms/16ksPef
you can add reference to System.Web and use System.Web.Configuration.WebConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString) from the class library project
A configuration file (app.config) which is defined in a class library project cannot be - automatically - consumed by the system. The only config file that can be consumed is the web.config file in web applications or *myexe.exe*.config in exe applications where exe file is *myexe.exe*.
So you seem to be trying to add app.config to the class library. That ain't gonna work.
It is possible to link a second config file to the web.config but that probbaly is no help to you.
Basically, what you need is a possibility to change a global parameter of your library from outside. Using app.config by itself does not give you that possibility straight away -- you have not exposed your library internal settings yet. With that in mind, one very straightforward way to achieve exposure is to create in your library an assigner for the app.config.
public static class Setter
{
public static void Set(string name, string value)
{
Properties.Settings.Default[name] = value;
}
}
Then, at web application start in global.asax, or elsewhere:
MyLibrary.Setter.Set("X", ConfigurationManager.ConnectionStrings["Y"].ConnectionString);
From your question I think you're building an n-layered application. I think you're better off the two options you mentioned.
You should just create a base class for your DAL (Data Access Layer) classes that will have a public property that contains that the connection string.
btw it will help you hide/secure your connection string instead of storing it in a file that could be easily read by anyone who have or gained access to your host
public class DALBase
{
public static string connString
{
get { return "Data Source=localhost\\SqlExpress;Initial Catalog=theDb Integrated Security=True"; }
}
}

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