Merging web.configs between projects
Asked Answered
D

2

12

I have a common web project which is used as a base for several "child" web projects. Is it possible to apply a web.config transform/merge between projects? Let's say the structure looks like this:

base project
  - web.config

child project
  - web.config
    - transform.config

Is it possible to make a pre build event or similar that merges the base project web.config with the child project web.config?

Deontology answered 2/1, 2018 at 13:27 Comment(5)
Why not use a Nuget package to populate your "Core" base project as a package and just overwrite what you need for your client. This way you can populate updates on the base across all custom applications that use those package.Novocaine
I've never used it so not sure how it should work but the web.config has automatic inherence from the parent folder no? so theoretically all you need to do is place those projects in a parent\child foldersDangle
@Novocaine Thanks but I'm not interested in a solution involving nuget, since we don't have a nuget feed atmDeontology
@ZivWeissman Yeah it applies for some settings but wouldn't work for things like connection stringsDeontology
How would you merge child web config with base web config? Do you mean that child web config is a transform for the base web config? i.e. does it have transform attributes, or is it a regular web config? if it's a regular config only, then what should the result be after merging child web config into base web config? If it's a transform itself then that at least is clear how to merge.Gravity
B
5

You can edit into separate file (transform.config) [1],[2] and:

Add an <appsettings> section and add your data as key/value pairs of the form:

<add key="xxx" value="xxxx" />

That's all to create new app.config file with settings in it.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="Child1" value="Child1_Value" />
    <add key="Child2" value="Child2_Value" />
  </appSettings>
</configuration>

And same for the connection string [3]:

<connectionStrings>
    <add name="yourConnectionStringName" 
         connectionString="yourConnectionString" 
         providerName="System.Data.SqlClient"/>
</connectionStrings>

And use configSource for the parent file:

<connectionStrings configSource="parentWeb.config"/>
Basrhin answered 4/1, 2018 at 19:32 Comment(0)
E
0

I've struggled recently with this kind of problem - though I was trying to merge two web.config files programmatically at runtime.

The following code works partially, for AppSettings and Settings sections (ConnectionStrings would have to be added), for build time you could wrap it in an executable:

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        var p = Server.MapPath("~/Web.user.config");
        if (File.Exists(p))
        {
            var fileMap = new ConfigurationFileMap(p); //Path to your config file
            var userConfig = ConfigurationManager.OpenMappedMachineConfiguration(fileMap);

            var globalConfig = WebConfigurationManager.OpenWebConfiguration("~/");
            var globalGroups = globalConfig.SectionGroups.Cast<ConfigurationSectionGroup>().ToList();

            CopySections(userConfig.Sections.Cast<ConfigurationSection>(), globalConfig.Sections.Cast<ConfigurationSection>());

            foreach (ConfigurationSectionGroup userGroup in userConfig.SectionGroups)
            {
                var globalGroup =  globalGroups.SingleOrDefault(g => g.SectionGroupName == userGroup.SectionGroupName);
                if (globalGroup != null)
                {
                    CopySections(userGroup.Sections.Cast<ConfigurationSection>(), globalGroup.Sections.Cast<ConfigurationSection>());
                }
            }

            globalConfig.Save();

        }
    }

    private void CopySections(IEnumerable<ConfigurationSection> source, IEnumerable<ConfigurationSection> target)
    {
        foreach (var sourceSection in source)
        {
            var targetSection = target.SingleOrDefault(s => s.SectionInformation.SectionName == sourceSection.SectionInformation.SectionName);
            if (targetSection != null)
            {
                var targetAppSettings = targetSection as AppSettingsSection;
                if (targetAppSettings != null)
                {
                    var sourceAppSettings = (AppSettingsSection) sourceSection;
                    foreach (KeyValueConfigurationElement keyValue in sourceAppSettings.Settings)
                    {
                        var targetSettings = targetAppSettings.Settings;

                        if (targetSettings.AllKeys.Any(k => k == keyValue.Key))
                        {
                            targetSettings.Remove(keyValue.Key);
                        }

                        targetSettings.Add(keyValue);
                    }
                }

                var targetClientSettings = targetSection as ClientSettingsSection;
                if (targetClientSettings != null)
                {
                    var sourceClientSettings = (ClientSettingsSection) sourceSection;
                    foreach (SettingElement keyValue in sourceClientSettings.Settings)
                    {
                        var targetSettings = targetClientSettings.Settings;
                        var existingSetting = targetSettings.Cast<SettingElement>().SingleOrDefault(e => e.Name == keyValue.Name);
                        if (existingSetting != null)
                        {
                            existingSetting.Value = keyValue.Value;
                        }
                    }
                }
            }
        }
    }
Epicanthus answered 11/1, 2018 at 16:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.