Search code examples
nugetnuget-package.net-standardxdt-transform

Nuget xdt transform does not work for config files


I have .NetStandard library. I'm going to use it in .NetFramework and .NetCoreApp applications.

It uses System.Configuration.ConfigurationManager package for work with config files. I need to transform these config files during my library installation.

I found 2 ways:

  1. tools folder in nuget package with install.ps1 file in it
  2. content folder with app.config.install.xdt file in it

Non of them is does not work - nuget doesn't run install.ps1, nuget doesn't transform App.config.

There is a code from csproj:

<ItemGroup>
  <Content Include="Content\app.config.install.xdt">
    <PackagePath>content</PackagePath>
  </Content>
</ItemGroup>

Nuget package contains this file... So I have no idea why it doesn't work.

Is this problem related to .NetStandard? What I'm doing wrong?


Solution

  • Executing ps1 scripts, and XDT transforms are both features that only work with packages.config, but not PackageReference. .NET Core (and I think .NET Standard) projects only work with SDK-style projects, and SDK style projects only support PackageReference. Packages.config only works with "old-style" projects, which may also PackageReference.

    The way that Microsoft's ASP.NET Core libraries deal with this difference is that they no longer read settings directly from web.config. Instead the program has to register callback functions that will modify an existing in-memory options object. For example

    services.AddMyService(options =>
        {
            options.setting = newValue;
        });
    

    This has some advantages to your users.

    1. They are no longer limited to storing the configuration value in the location the library author demanded. They can choose to load configuration from a database, a configuration service, an xml file, a json file, or just hard-code it in the app. But it lets each developer choose what's best for their own system.
    2. If the user overrides a setting that the package puts in the config file, and each update of the package overrides the user's preference, the user gets annoyed that the package doesn't respect their choice to change the default.
    3. If the user doesn't want to override a setting that the package put in the config file, and the package author doesn't want to overwrite the config file each update, then it's very difficult for the package author to change a default value.

    ASP.NET Core's new model is better for everyone because the package author creates the options object and pre-populates it with default values and then call the user's delegate method allowing them to change the settings they care about. If the package author wants to change a default value, they do so in their own code, publish a new package, and users that don't change the value get the new default, and users who explicitly set the value in their code keep using the value they want to, from whatever configuration store they want.

    So, the TL:DR answer is that you can't do what you asked for with PackageReference projects, but I hope my longer answer has given you ideas how you can redesign your library which gives better both the package author and package user a better experience.