Home > Back-end >  appsettings.json being read from $(ProjectDir) not $(OutDir)
appsettings.json being read from $(ProjectDir) not $(OutDir)

Time:10-14

Running AspNetCore locally in VisualStudio I am seeing appsettings.json being served from the source directory rather than from the output directory under bin. This is annying because I have a build step to set a value in it

    <PropertyGroup>
        <TargetFramework>net6.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>disable</ImplicitUsings>
    <AzureBuild>$(Build)</AzureBuild>

    <BuildName Condition=" '$(AzureBuild)' == '' ">$([System.Environment]::MachineName)_$([System.DateTime]::Now.ToString(yyyy-MM-dd_HH-mm))</BuildName>
    <BuildName Condition=" '$(AzureBuild)' != '' ">$(AzureBuild)</BuildName>
</PropertyGroup>

  <UsingTask TaskName="ReplaceFileText" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
    <ParameterGroup>
      <InputFilename ParameterType="System.String" Required="true" />
      <OutputFilename ParameterType="System.String" Required="true" />
      <MatchExpression ParameterType="System.String" Required="true" />
      <ReplacementText ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Using Namespace="System" />
      <Using Namespace="System.IO" />
      <Using Namespace="System.Text.RegularExpressions" />
      <Code Type="Fragment" Language="cs">
        <![CDATA[  
          File.WriteAllText(
            OutputFilename,
            Regex.Replace(File.ReadAllText(InputFilename), MatchExpression, ReplacementText)
            );
        ]]>
      </Code>
    </Task>
  </UsingTask>

  <Target Name="appsettingsSetBuildId" BeforeTargets="AfterBuild">
    <!-- "Build" doesn't work - maybe it's not a target? -->
    <ReplaceFileText InputFilename="$(OutDir)appsettings.json" OutputFilename="$(OutDir)appsettings.json" MatchExpression="{BuildName}" ReplacementText="$(BuildName)" />
    <Message Importance="High" Text="Replaced {BuildName} with $(BuildName) in $(OutDir)appsettings.json." />
  </Target>

In my bin\Debug\netcoreapp3.1 directory I see that appsetting.json has been updated, but in code I am seeing the value from the appsettings.json in the source directory.

What's going on?!

Update: also not working (seeing value from source file) after publishing from VisualStudio to an Azure web app.

CodePudding user response:

In program.cs you could set the base path of IConfigrationBuiler as below,if you don't set,the default value would be solutionpath when you debug ,and you could read settings from other json files with the codes below

public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureAppConfiguration((hostingContext, config) =>
                    {
                        //default basepath is your SolutionPath
                        config.SetBasePath("somepath");
                        config.AddJsonFile("somejson.json",
                        optional: true,
                        reloadOnChange: true);
                    })
                    .ConfigureWebHostDefaults(webBuilder =>
                    {                    
                        webBuilder.UseStartup<Startup>();
                    });

Also,you could update appsettings.json from your solution path together with that in bin floder

<ReplaceFileText InputFilename="$(InputPath)appsettings.json" OutputFilename="$(InputPath)appsettings.json" MatchExpression="Nihao"  ReplacementText="Hellow" />

CodePudding user response:

Can't work out what's going on with the config file -- quite disappointingly. So I've used a custom assembly attribute instead

    [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
    public class BuildNameAttribute : Attribute
    {
        public string BuildName { get; set; }

        public BuildNameAttribute(string buildName)
        {
            BuildName = buildName;
        }

        public static string GetBuildName()
        {
            Assembly a = Assembly.GetEntryAssembly();
            BuildNameAttribute bna = a.GetCustomAttribute<BuildNameAttribute>();
            return bna?.BuildName ?? "";
        }
    }

and

    <AzureBuild>$(Build)</AzureBuild>
    <BuildName Condition=" '$(AzureBuild)' == '' ">$([System.Environment]::MachineName)_$([System.DateTime]::Now.ToString(yyyy-MM-dd_HH-mm))</BuildName>
    <BuildName Condition=" '$(AzureBuild)' != '' ">$(AzureBuild)</BuildName>
  </PropertyGroup>

  <ItemGroup>
    <AssemblyAttribute Include="Company.BuildNameAttribute">
      <_Parameter1>$(BuildName)</_Parameter1>
    </AssemblyAttribute>
  </ItemGroup>

  • Related