locked
Custom Configuration Sections in Web.config RRS feed

  • Question

  • User-1664018040 posted
    I have custom configuration sections in my Web.config file, both in-house developed, and third party, e.g.:
    <configSections>
    <section name="mySection" type="ClassLibrary1.MySection,ClassLibrary1,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null" />
    </configSections>
    When I build my web deployment project, I get this error:

    C:\Program Files\MSBuild\Microsoft\WebDeployment\v8.0\Microsoft.WebDeployment.targets(613,9): error : An error occurred creating the configuration section handler for mySection: Could not load file or assembly 'ClassLibrary1.MySection,ClassLibrary1,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. (C:\WebSites\WebSite1Deploy\Debug\web.config line 4)

    If I copy the offending assembly to the same directory as my project file, it still breaks. I thought I might need to copy it to the $(MSBinPath) directory (in my case C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727), but that only solved it for running MSBuild from the command-line.

    After a bit of investigation, it seems like it is using the rules of the AppDomain to locate the assembly. So this means the framework runtime directory when running from MSBuild.exe, and the IDE directory for doing a build from Visual Studio (i.e. where devenv.exe lives – C:\Program Files\Microsoft Visual Studio 8\Common7\IDE).

    Fair enough. I can live with this if I manually or automatically (using Copy tasks) get the assemblies into these two places. But it’s ugly. I don’t really want to be fricking around with assemblies in the runtime and IDE directories just to get a web site to build, and I’m bound to hit file locking issues anyway.

    At the end of the day, what does the build need these assemblies for? My guess is it’s only using them to load the sections from Web.config just so it can immediately replace them with the replacement files. It doesn’t care about the meaning of the configuration sections, or what they contain.

    So, my workaround was to create a new MSBuild task that does a straight XML replacement of the Web.config sections (I’m sure there are thousands of versions of such a task out there), since config files are glorified XML files, and uses the same inputs as the ReplaceConfigSections task (i.e. the @(WebConfigReplacementFiles) list).

    I know I’m not the only one who has or who will hit this, since custom configuration sections are not uncommon. I’d strongly urge the ASP.NET team to consider changing the ReplaceConfigSections task to treat Web.config as XML, not a Configuration document, in a future release if they have not already done so.

    Thanks,
    Scott

    Wednesday, June 7, 2006 8:56 PM

All replies

  • User-1252191800 posted
    I am facing same problem in my .Net application with app.config file. Do u know is anything done from MS side on this? If no, could you please explain more on your workaround? DO you mean that i have to read the config file just like a XML file and parse it? or anything else? I am pretty new to this. thank you.... g.P
    Thursday, August 2, 2007 2:36 AM
  • User-1664018040 posted

    I don't know whether or not this has been resolved in VS2005 SP1. Maybe it has - give it a go. The truth is, I am no longer using Web Deployment Projects, so this isn't a problem for me anymore. But as for my workaround - I meant you would need to create a custom MSBuild task that does the job of the ReplaceConfigSections task, but internally instead of using the System.Configuration namespace, just use System.Xml.

    Thursday, August 2, 2007 2:51 AM
  • User-484987990 posted

    I'm getting this problem, Scott, and we're using Sp1. I wsa hoping you might have had a new MSBuild task that does an Xml replacement, so i could use that instead. bummer :(

     this problem is killing me big time. I wish there was some way to define where the .dll's are, in the msbuild deployment project xml data or something.

    Tuesday, October 16, 2007 10:36 PM
  • User1994334238 posted

    In using your custom configuration section classes the ReplaceConfigSections task gains the ability to validate (or throw errors) when an invalid XML substitution is made.  An alternate to writing your own task to perform a vanilla XML substitution would be to write a task to load the desired assembly into memory before the WDP merge target.  The following (stripped down) class works for me (no warranties, use at your own risk etc [:)]).

    namespace SampleBuildTask
    {
        public class LoadAssemblies : Task
        {
            private ITaskItem[] assemblyFiles;

            public override bool Execute()
            {
                AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

                foreach (ITaskItem item in AssemblyFiles)
                {
                    FileInfo asm = new FileInfo(item.GetMetadata("Identity"));
                    if (asm.Exists)
                        Assembly.Load(LoadFile(asm));
                }

                return true;
            }

            [Required]
            public ITaskItem[] AssemblyFiles
            {
                get { return assemblyFiles; }
                set { assemblyFiles = value; }
            }

            static private byte[] LoadFile(FileInfo file)
            {
                using (FileStream fs = file.OpenRead())
                {
                    byte[] buffer = new byte[(int)fs.Length];
                    fs.Read(buffer, 0, buffer.Length);
                    return buffer;
                }
            }

            static private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
            {
                foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
                    if (string.Compare(assembly.FullName, args.Name, StringComparison.OrdinalIgnoreCase) == 0)
                        return assembly;

                throw new ArgumentException("Could not find the assembly!");
            }
        }
    }

     

    Compile this into SampleBuildTask.dll (you'll need references to Microsoft.Build.Framework and Microsoft.Build.Utilities) and place it in the MSBuild extensions directory (C:\Program Files\MSBuild).  Edit your WDP project file adding at the bottom:

      <UsingTask TaskName="LoadAssemblies" AssemblyFile="$(MSBuildExtensionsPath)\SampleBuildTask.dll" />
      <ItemGroup>
        <AssemblyFiles Include="$(Configuration)\bin\ClassLibrary1.dll" />
      </ItemGroup>
      <Target Name="BeforeMerge">
        <LoadAssemblies AssemblyFiles="@(AssemblyFiles)" />
      </Target>

    Where ClassLibrary1.dll is the name of the assembly of the custom configuration section (in your example) that previously caused the WDP build to fail.  Now, before the merge is completed your assembly ClassLibrary1, which is in the bin directory of the compiled website, is ready and in-memory for the ReplaceConfigSections task.

    Hope this helps people stuck facing this, um, feature, much like I was.

    Simon.

    PS: The code is loaded into the AppDomain of MSBuild (which is most likely the default one) meaning the only way reload the class definition is to restart VS2005.  Perhaps there is an option to cause MSBuild to run in a seperate AppDomain?

    Tuesday, March 11, 2008 3:23 PM
  • User-1843907661 posted

    Tried your magic source code. The code itself seems working fine, but however that didn`t help me to resolve problem with replacement of custom section.

    This is all that I could get from MSBuild:

      Updating web.config: RootPath = C:\p4\PRCHAT\CHaT\main\source\PartnerRe.CHaT.
      TestDataLoader\bin\Release\, ValidateSections = False, UseExternalConfigSourc
      e = True
      Replacing section appSettings with file appSettings.config
      Replacing section connectionStrings with file connectionStrings.config
    C:\p4\PRCHAT\CHaT\main\build\DataLoader.targets(50,3): error : An error occurre
    d creating the configuration section handler for dataLoader: Could not load fil
    e or assembly 'PartnerRE.Chat.TestDataLoader' or one of its dependencies. The p
    arameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG)) (C:\
    p4\PRCHAT\CHaT\main\source\PartnerRe.CHaT.TestDataLoader\bin\Release\web.config
     line 5)

      Update of web.config Failed.


    CoreReplaceDataLoaderWebConfigSections:

      Updating web.config: RootPath = C:\XXX\bin\Release\, ValidateSections = False, UseExternalConfigSource = True

      Replacing section appSettings with file appSettings.config

      Replacing section connectionStrings with file connectionStrings.config

    C:\XXX\DataLoader.targets(50,3): error : An error occurred creating the configuration section handler for dataLoader: Could not load fil

    e or assembly 'XXX.TestDataLoader' or one of its dependencies. The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG)) (C:\XXX\bin\Release\web.config line 5)

      Update of web.config Failed.

    Even Google wasn`t able to find any blogs regarding E_INVALIDARG in ReplaceConfigSections. Please help!

    Monday, May 31, 2010 11:50 AM