Skip to content

Commit

Permalink
Fixes appsettings.[EnvironmentName].json (#5421)
Browse files Browse the repository at this point in the history
* Updated ConfigurationBuilderExtensions to take HostBuilderContext so it can get the EnviornmentName and load the propper appsettings.
Fixed bug in loading appsettings.EnvironmentName.json
Added base unit tests

* Updated Adaptive.Runtime project to target netstandard 2.0 and net core 3.1

* Added conditional references based on target framework

* Forced adding ignored files so we can test.
  • Loading branch information
gabog authored Apr 2, 2021
1 parent 1c5e016 commit 402bc02
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime.Settings;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Microsoft.Extensions.Hosting;

namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime.Extensions
{
Expand All @@ -15,8 +14,6 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime.Extensions
/// </summary>
public static class ConfigurationBuilderExtensions
{
private const string AppSettingsFileName = @"appsettings.json";
private const string AppSettingsDevelopmentFileName = @"appsettings.Development.json";
private const string DialogFileExtension = ".dialog";

/// <summary>
Expand All @@ -25,16 +22,17 @@ public static class ConfigurationBuilderExtensions
/// <param name="builder">
/// The <see cref="IConfigurationBuilder"/> to supply with additional in-memory configuration settings.
/// </param>
/// <param name="hostBuilderContext">A <see cref="HostBuilderContext"/> instance with information about the host.</param>
/// <param name="applicationRoot">
/// The application root directory. When running in local development mode from Composer, this is determined
/// to be three directory levels above where the runtime application project is ejected, i.e. '../../..'.
/// </param>
/// <returns>
/// Supplied <see cref="IConfigurationBuilder"/> instance with additional in-memory configuration provider.
/// </returns>
public static IConfigurationBuilder AddBotRuntimeConfiguration(this IConfigurationBuilder builder, string applicationRoot)
public static IConfigurationBuilder AddBotRuntimeConfiguration(this IConfigurationBuilder builder, HostBuilderContext hostBuilderContext, string applicationRoot)
{
return AddBotRuntimeConfiguration(builder, applicationRoot, settingsDirectory: null);
return AddBotRuntimeConfiguration(builder, hostBuilderContext, applicationRoot, null);
}

/// <summary>
Expand All @@ -43,6 +41,7 @@ public static IConfigurationBuilder AddBotRuntimeConfiguration(this IConfigurati
/// <param name="builder">
/// The <see cref="IConfigurationBuilder"/> to supply with additional in-memory configuration settings.
/// </param>
/// <param name="hostBuilderContext">A <see cref="HostBuilderContext"/> instance with information about the host.</param>
/// <param name="applicationRoot">
/// The application root directory. When running in local development mode from Composer, this is determined
/// to be three directory levels above where the runtime application project is ejected, i.e. '../../..'.
Expand All @@ -56,21 +55,28 @@ public static IConfigurationBuilder AddBotRuntimeConfiguration(this IConfigurati
/// </returns>
public static IConfigurationBuilder AddBotRuntimeConfiguration(
this IConfigurationBuilder builder,
HostBuilderContext hostBuilderContext,
string applicationRoot,
string settingsDirectory)
{
// Add in-memory properties for the bot runtime that depend on the environment and application root
AddBotRuntimeProperties(builder, applicationRoot);
if (hostBuilderContext == null)
{
throw new ArgumentNullException(nameof(hostBuilderContext));
}

IConfiguration configuration = builder.Build();
if (string.IsNullOrWhiteSpace(applicationRoot))
{
throw new ArgumentNullException(nameof(applicationRoot));
}

var applicationRootPath = configuration.GetValue<string>(ConfigurationConstants.ApplicationRootKey);

var appSettingsConfigFilePath = Path.GetFullPath(Path.Combine(applicationRootPath, settingsDirectory, AppSettingsFileName));
var developerSettingsConfigFilePath = Path.GetFullPath(Path.Combine(applicationRootPath, AppSettingsDevelopmentFileName));
// Add in-memory properties for the bot runtime that depend on the environment and application root
AddBotRuntimeProperties(builder, applicationRoot);

builder.AddJsonFile(appSettingsConfigFilePath, optional: true, reloadOnChange: true);
builder.AddJsonFile(developerSettingsConfigFilePath, optional: true, reloadOnChange: true);
// Load appsettings.
var appSettingsConfigFilePath = Path.Combine(applicationRoot, settingsDirectory, "appsettings.json");
var developerSettingsConfigFilePath = Path.Combine(applicationRoot, settingsDirectory, $"appsettings.{hostBuilderContext.HostingEnvironment.EnvironmentName}.json");
builder.AddJsonFile(appSettingsConfigFilePath, optional: true, reloadOnChange: true)
.AddJsonFile(developerSettingsConfigFilePath, optional: true, reloadOnChange: true);

// Use Composer luis and qna settings extensions
builder.AddComposerConfiguration();
Expand All @@ -93,11 +99,6 @@ public static IConfigurationBuilder AddBotRuntimeConfiguration(
/// </param>
private static void AddBotRuntimeProperties(IConfigurationBuilder builder, string applicationRoot)
{
if (string.IsNullOrEmpty(applicationRoot))
{
throw new ArgumentNullException(nameof(applicationRoot));
}

var settings = new Dictionary<string, string>
{
{ ConfigurationConstants.ApplicationRootKey, applicationRoot },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,36 @@
</PropertyGroup>

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime</PackageId>
<Description>Library for building Adaptive Runtime bots using the Bot Framework SDK</Description>
<Summary>Library for building Adaptive Runtime bots using the Bot Framework SDK</Summary>
<ContentTargetFolders>content</ContentTargetFolders>
<TargetFrameworks>netstandard2.0;netcoreapp3.1</TargetFrameworks>
<PackageId>Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime</PackageId>
<Description>Library for building Adaptive Runtime bots using the Bot Framework SDK</Description>
<Summary>Library for building Adaptive Runtime bots using the Bot Framework SDK</Summary>
<ContentTargetFolders>content</ContentTargetFolders>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>Full</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<!-- Explicitly set to 5.0.1 for those built against 2.0-->
<PackageReference Include="System.Text.Encodings.Web" Version="5.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" Version="2.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.1.0" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
<PackageReference Include="Microsoft.Bot.Builder.AI.Luis" Condition=" '$(ReleasePackageVersion)' == '' " Version="$(LocalPackageVersion)" />
<PackageReference Include="Microsoft.Bot.Builder.AI.Luis" Condition=" '$(ReleasePackageVersion)' != '' " Version="$(ReleasePackageVersion)" />
<PackageReference Include="Microsoft.Bot.Builder.AI.QnA" Condition=" '$(ReleasePackageVersion)' == '' " Version="$(LocalPackageVersion)" />
Expand All @@ -39,10 +56,6 @@
<PackageReference Include="Microsoft.Bot.Builder.Integration.ApplicationInsights.Core" Condition=" '$(ReleasePackageVersion)' != '' " Version="$(ReleasePackageVersion)" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Condition=" '$(ReleasePackageVersion)' == '' " Version="$(LocalPackageVersion)" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Condition=" '$(ReleasePackageVersion)' != '' " Version="$(ReleasePackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.8" />
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.8" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.8" />
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"testSetting": "DevEnvironmentValue"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"testSetting": "TestEnvironmentValue"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"testSetting": "NoEnvironmentValue"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Xunit;

namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime.Tests.Extensions
{
public class ConfigurationBuilderExtensionsTests
{
[Fact]
public void ParameterValidation()
{
var sut = new ConfigurationBuilder();
Assert.Throws<ArgumentNullException>(() =>
{
sut.AddBotRuntimeConfiguration(null, "blah");
});

Assert.Throws<ArgumentNullException>(() =>
{
sut.AddBotRuntimeConfiguration(new HostBuilderContext(new Dictionary<object, object>()), null);
});

Assert.Throws<ArgumentNullException>(() =>
{
sut.AddBotRuntimeConfiguration(new HostBuilderContext(new Dictionary<object, object>()), string.Empty);
});
}

[Theory]
[InlineData(null, "NoEnvironmentValue")]
[InlineData("Development", "DevEnvironmentValue")]
[InlineData("Test", "TestEnvironmentValue")]
[InlineData("NotThere", "NoEnvironmentValue")]
public void LoadsAppSettings(string environmentName, string expectedSetting)
{
// Arrange
var mockBuilderContext = new HostBuilderContext(new Dictionary<object, object>())
{
HostingEnvironment = new TestHostingEnvironment { EnvironmentName = environmentName }
};
var applicationRoot = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Extensions", "ConfigurationBuilderExtensionsFiles");

// Act
var sut = new ConfigurationBuilder();
sut.AddBotRuntimeConfiguration(mockBuilderContext, applicationRoot, "settings");
var actualConfig = sut.Build();

// Assert runtime properties.
Assert.Equal(applicationRoot, actualConfig["applicationRoot"]);
Assert.Equal("RootDialog.dialog", actualConfig["defaultRootDialog"]);

// Assert appsettings values are loaded based on EnvironmentName.
Assert.Equal(expectedSetting, actualConfig["testSetting"]);
}

#if NETCOREAPP2_1
/// <summary>
/// Help implementation of <see cref="Microsoft.Extensions.Hosting.IHostEnvironment"/> use for testing.
/// </summary>
private class TestHostingEnvironment : Microsoft.Extensions.Hosting.IHostingEnvironment
#else
private class TestHostingEnvironment : IHostEnvironment
#endif
{
public string EnvironmentName { get; set; }

public string ApplicationName { get; set; }

public string ContentRootPath { get; set; }

public IFileProvider ContentRootFileProvider { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@
<Configurations>Debug;Release</Configurations>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="2.1.0" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="xunit" Version="2.4.1" />
Expand All @@ -22,4 +30,10 @@
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime\Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Dialogs.Declarative\Microsoft.Bot.Builder.Dialogs.Declarative.csproj" />
</ItemGroup>
</Project>

<ItemGroup>
<None Update="Extensions\ConfigurationBuilderExtensionsFiles\**\*.*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

0 comments on commit 402bc02

Please sign in to comment.