jason-roberts / FeatureToggle

Simple, reliable feature toggles in .NET

Home Page:http://dontcodetired.com/blog/?tag=/featuretoggle

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

AppSettingsProvider doesn't appear to correctly load from appSettings.json?

AdrianLThomas opened this issue · comments

Hi,

I get this exception at runtime:
System.IO.FileNotFoundException: The configuration file 'appSettings.json' was not found and is not optional. The physical path is '[removed]\src\api\bin\Debug\netcoreapp1.1\appSettings.json'.

If I manually place the appSettings file in that location, the exception changes to the following:
FeatureToggle.ToggleConfigurationError: The key 'FeatureToggle.ValuesFeature' was not found in AppSettings

This is the appSettings.json file:

{
  "FeatureToggle":{
    "ValuesFeature": "false",
    "NavigationFeature": "true"
  }
}

If I write my own settings provider to read from the appSettings file then it works fine - but looking at the sample code and documentation shouldn't this work?

@AdrianLThomas thanks for reporting this, I'll look into it.

@AdrianLThomas Hi Adrian, when using in ASP.NET Core you need to explicitly set the IConfigurationRoot otherwise the default behavior (e.g. when running in console app) is to look in the bin directory.

Example ASP.NET Core config: https://github.com/jason-roberts/FeatureToggle/blob/master/src/Examples/AspDotNetCoreExample/Startup.cs#L31-L41

Then in controller us DI: https://github.com/jason-roberts/FeatureToggle/blob/master/src/Examples/AspDotNetCoreExample/Controllers/HomeController.cs#L17

This is because the default config location is calculated using AppContext.BaseDirectory https://github.com/jason-roberts/FeatureToggle/blob/master/src/FeatureToggle.Shared/Internal/AppSettingsProvider.cs#L38 - as I understand it this resolves to the bin folder, whereas in ASP.NET Core we want the root folder than contains the appsettings.json

Hi Jason,
Thanks for your reply, and apologies for the delay.

So I did try explicitly setting the AppSettingsProvider, but I still get the error I mentioned in the original post. I've created a branch here that reproduces the issue: AdrianLThomas/Angular-and-ASP.NET-Core-Feature-Toggling@1dba93b

Here's the full error message:

$ dotnet run
Hosting environment: Production
Content root path: C:\Src\adrianlthomas.github.com\Angular-and-ASP.NET-Core-Feature-Toggling\src\api
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HL5SH1KQC7RD": An unhandled exception was thrown by the application.
FeatureToggle.ToggleConfigurationError: The key 'FeatureToggle.ValuesFeature' was not found in AppSettings
   at FeatureToggle.Internal.AppSettingsProvider.ValidateKeyExists(String key)
   at FeatureToggle.Internal.AppSettingsProvider.EvaluateBooleanToggleValue(IFeatureToggle toggle)
   at api.Controllers.FeaturesController.<>c.<Get>b__2_0(IFeatureToggle x) in C:\Src\adrianlthomas.github.com\Angular-and-ASP.NET-Core-Feature-Toggling\src\api\Controllers\FeaturesController.cs:line
 31
   at System.Linq.Enumerable.SelectListIterator`2.MoveNext()
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector)
   at api.Controllers.FeaturesController.Get() in C:\Src\adrianlthomas.github.com\Angular-and-ASP.NET-Core-Feature-Toggling\src\api\Controllers\FeaturesController.cs:line 33
   at lambda_method(Closure , Object , Object[] )
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__27.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__25.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextResourceFilter>d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeAsync>d__20.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.<Invoke>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame`1.<RequestProcessingAsync>d__2.MoveNext()

Great - thanks @AdrianLThomas - will take a look...

@AdrianLThomas the nested json config is as of rc2, I updated your branch to NuGet 4.0.0-rc2 and both the values and features APIs now work.

@jason-roberts that's great! Thank you. I was using RC1 at the time, looks like the recent update has sorted this :-)