|
| 1 | +# MicrosoftConfigurationBuilders FAQ |
| 2 | + |
| 3 | +TODO - search for 'expand' |
| 4 | +We get a lot of questions about `KeyValueConfigBuilders` - and Configuration Builders in general. Here are |
| 5 | +some of the most frequent along with answers that are hopefully helpful. |
| 6 | + |
| 7 | + |
| 8 | +<details> |
| 9 | + <summary><a name="expand"><b>Why did you get rid of 'Expand' mode?</b></a></summary> |
| 10 | + |
| 11 | + Because 'Expand' mode operated in the 'ProcessRawXml' phase of configuration building, while the other |
| 12 | + modes all operate in 'ProcessConfigurationSection.' It was a bit of a balancing act trying to develop |
| 13 | + features that work across both phases - a challenge which is sometimes quite difficult given the lack of |
| 14 | + information we have about the section we are processing in 'ProcessRawXml.' |
| 15 | + |
| 16 | + For example, V3 of these builders tries to accomodate 'ConfigurationManager.OpenConfiguration()' |
| 17 | + scenarios where apps want to read a config file that is not their own. In these cases, we need to |
| 18 | + know information about the file and section we are processing that we just can't know in the |
| 19 | + 'ProcessRawXml' phase. Another example is the [parameters from appSettings](KeyValueConfigBuilders.md#appsettings-parameters) |
| 20 | + feature which was disabled in 'Expand' mode while processing the appSettings section, but can |
| 21 | + still be used somewhat functionally when executing any of the modes that operate in 'ProcessConfigurationSection.' |
| 22 | + |
| 23 | + To make things simpler across the board, 'Expand' mode was replaced with 'Token' mode which should |
| 24 | + operate in a fairly similar manner with the added benefit of being less prone to producing invalid |
| 25 | + XML to muck things up. :smiley: |
| 26 | +</details> |
| 27 | + |
| 28 | +<details> |
| 29 | + <summary><a name="newhandler"><b>Can you add a `SectionHandler` for section `XYZ?`</b></a></summary> |
| 30 | + |
| 31 | + We have included default `SectionHandlers` for `<appSettings>` and `<connectionStrings>` because they |
| 32 | + are by far the most commonly used "key/value" config sections. But we introduced the `SectionHandler<T>` |
| 33 | + API to allow for more sections to be processed. |
| 34 | + |
| 35 | + We don't currently feel that there are any other sections out there that have enough demand to |
| 36 | + warrant including a default section handler in the base package that everybody is required to use. |
| 37 | + That does not mean that section handlers for other sections is not ever a valid scenario, and you |
| 38 | + are of course welcome and encouraged to leverage the section handler feature if it suits your needs. |
| 39 | + That is why we introduced the feature afterall. |
| 40 | +</details> |
| 41 | + |
| 42 | +<details> |
| 43 | + <summary><a name="applicationsettings"><b>Can you add a `SectionHandler` for the client `ApplicationSettings` section?</b></a></summary> |
| 44 | + |
| 45 | + See [above](#newhandler). `ApplicationSettings` is less commonly used. But more problematically, it |
| 46 | + isn't really a standard .Net configuration section like it appears to be on first glance. The classes |
| 47 | + that support ApplicationSettings provide a strict and strongly typed window into what looks like a |
| 48 | + standard configuration section in your app.config file. While we can easily write a section handler |
| 49 | + for the `ClientSettingsSection` ([example](../samples/SampleSectionHandlers/ClientSettingsSectionHandler.cs)) |
| 50 | + it won't integrate into the ApplicationSettings framework seamlessly like one might expect. The |
| 51 | + ApplicationSetting framework has already determined the number and names (including casing, which |
| 52 | + is problematic in 'Greedy' mode) of all the settings it will present before the base configuration |
| 53 | + system even gets a crack at reading from the config file. So you can't *add* new values with 'Greedy' |
| 54 | + mode, and you can't override existing values in 'Greedy' mode if you don't properly match |
| 55 | + casing - despite the fact that ApplicationSettings is supposed to be case-insensitive. |
| 56 | + |
| 57 | + If you wish, you can use the [sample section handler](../samples/SampleSectionHandlers/ClientSettingsSectionHandler.cs) |
| 58 | + to process ApplicationSettings in your application, but know that the use case is rather limited. |
| 59 | + It will work in 'Strict' mode... and maybe require some prodding to force the ApplicationSettings |
| 60 | + framework to forget the settings it's seen before and decide to look back into the config file to |
| 61 | + get new values. |
| 62 | + |
| 63 | + You can read more about the architecture of the AppliationSettings framework [here](https://docs.microsoft.com/en-us/dotnet/desktop/winforms/advanced/application-settings-architecture?view=netframeworkdesktop-4.8) |
| 64 | + to see how it builds layers on top of the standard config system that often obscure any changes or |
| 65 | + additional settings that appear in the `ClientSettingsSection` but won't be seen in |
| 66 | + `MyApp.Properties.Settings`. That set of articles is also a good starting point for learning |
| 67 | + about `SettingsProvider` and how that might be leveraged to accomplish configuration injection |
| 68 | + through a different mechanism in the case when applications must use ApplicationSettings. |
| 69 | +</details> |
| 70 | + |
| 71 | +<details> |
| 72 | + <summary><a name="azureappservices"><b>Do ConfigBuilders break the 'Application Settings' feature of Azure AppServices?</b></a></summary> |
| 73 | + |
| 74 | + Maybe a little? It does appear that adding a 'configBuilders' tag to your 'appSettings' or 'connectionStrings' |
| 75 | + sections confuses the injection logic for the Azure AppServices "Application Settings" feature. I do not |
| 76 | + have any insight as to why that is other than to say that the two features "grew up" contemporaneously, so |
| 77 | + they were probably not aware that configBuilders could exist. |
| 78 | + |
| 79 | + But all is not lost. The "Application Settings" feature injects all it's values into the environment of |
| 80 | + the service. So while using ConfigBuilders might interfere with the automatic injection of those values, |
| 81 | + you can also use ConfigBuilders to pull those values back in. See [this issue comment](#133#issuecomment-1049520479) |
| 82 | + for more details. |
| 83 | +</details> |
| 84 | + |
| 85 | +<details> |
| 86 | + <summary><a name="iisschema"><b>Why does IIS/inetmgr complain about configBuilders?</b></a></summary> |
| 87 | + |
| 88 | + Because IIS config tools are old and cranky, just like the old .Net config system wanted them to be. :smiling_imp: |
| 89 | + |
| 90 | + The old .Net config system is supposed to be quite rigid and super-strongly typed. So when IIS developed |
| 91 | + tools to work with config, they took steps to ensure they didn't break folks by creating invalid configuration. |
| 92 | + In particular, they decided to use XML schema's to ensure the XML they save is on the up-and-up. (Just |
| 93 | + like Visual Studio does. But Visual Studio gets updated quite a bit more frequently than IIS tools and |
| 94 | + has a lower bar for fixing nagging bugs that have a workaround - and was therefore better equipped to |
| 95 | + change with the times when .Net config added new features and sections. Also, failing schema validation |
| 96 | + in Visual Studio simply resulted in red squiggles instead of error dialogs. :frowning:) |
| 97 | + |
| 98 | + The workaround is really quite simple, but it isn't something we can do in these packages. As suggested |
| 99 | + in #126, simply add a schema file for IIS to help it understand that configBuilders are ok on some |
| 100 | + sections. |
| 101 | + |
| 102 | + `%systemroot%\system32\inetsrv\config\schema\configBuilders_schema.xml` |
| 103 | + ```xml |
| 104 | +<configSchema> |
| 105 | + <sectionSchema name="appSettings"> |
| 106 | + <attribute name="configBuilders" type="string"/> |
| 107 | + </sectionSchema> |
| 108 | + <sectionSchema name="connectionStrings"> |
| 109 | + <attribute name="configBuilders" type="string"/> |
| 110 | + </sectionSchema> |
| 111 | +</configSchema> |
| 112 | + ``` |
| 113 | + |
| 114 | +</details> |
| 115 | + |
| 116 | +<details> |
| 117 | + <summary><a name="windowscontainers"><b>My config builder isn't working in my Windows container.</b></a></summary> |
| 118 | + |
| 119 | + That's a statement, not a question. But here's a likely explanation. |
| 120 | + |
| 121 | + Windows containers only modify the environment block of the EntryPoint process. So if your application |
| 122 | + is running as a service (like IIS/ASP.Net apps) or some other process not directly created by the |
| 123 | + EntryPoint, any environment variables set when starting the container will not be visible to your |
| 124 | + app. |
| 125 | + |
| 126 | + To work around this issue, [ASP.Net](https://github.com/microsoft/dotnet-framework-docker/tree/main/src/aspnet) |
| 127 | + and [IIS](https://github.com/microsoft/iis-docker) container images rely on a `ServiceMonitor.exe` |
| 128 | + utility to be the entry point for the container, and this utility proactively modifies the environment |
| 129 | + of the worker process with any additional environment variables passed to docker run. |
| 130 | + |
| 131 | + For IIS/ASP.Net workloads, do try to use an IIS/ASP.Net derived container that uses `ServiceMonitor.exe.` |
| 132 | + For other workloads, try making your app the EntryPoint, or try a similar approach to how IIS/ASP.Net |
| 133 | + handle this... possibly even leveraging [ServiceMonitor.exe](https://github.com/Microsoft/IIS.ServiceMonitor) |
| 134 | + itself. |
| 135 | +</details> |
| 136 | + |
| 137 | +<details> |
| 138 | + <summary><a name="vstyperes"><b>Why do I get an error in Visual Studio when I switch my web app to use IIS instead of IISExpress?</b></a></summary> |
| 139 | + |
| 140 | + Many reasons. The gist of the situation is this... When you switch your web application to run in IIS |
| 141 | + instead of IISExpress, Visual Studio tries to read your config file to parse connection strings. I |
| 142 | + believe it's looking for 'LocalDB', but that's not really important. Your web app's config file is |
| 143 | + obviously not part of the process configuration for devenv.exe, so VS opens it via |
| 144 | + `ConfigurationManager.OpenConfiguration()` or something similar. Prior to V3, this was likely to |
| 145 | + result in failures in many of these key/value config builders if they were applied to the |
| 146 | + `<connectionStrings>` section. |
| 147 | + |
| 148 | + In V3, we handle the `ConfigurationManager.OpenConfiguration()` scenario better, but we can still |
| 149 | + get tripped up by the insanely complicated way Visual Studio manages reference binding. As a result, |
| 150 | + there may be version mis-matches when trying to load some builders. The Azure builders seem particularly |
| 151 | + vulnerable to this. I haven't found a good way to deal with this. |
| 152 | + |
| 153 | + **However,** even though the error appears in a scary dialog box, it does not affect the behavior of |
| 154 | + your application. When running/debugging your app on local IIS, the config builders are still able to |
| 155 | + execute as expected. |
| 156 | +</details> |
0 commit comments