So myself and @anotherchris are in the process of doing our first .Net Core port and we chose Syringe to play with.
I have been working on porting over our service/API layer, and things had been going really well until it got to loading up configuration from file. Up until this point we had 3/4 different config files that lived on disk, and they could either be in the local directory or live in ProgramData/Syringe.
The people over at Microsoft have supplied us with a really cool way of loading config from many places in one easy to use pattern: Configuration.
Everything seemed to be working fine, until I noticed that all the values in my configuration were the default ones, and it took me a very long time to understand why.
Here is a copy of my start up where the configuration was setup:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json".ToLower(), optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddOptions();
services.AddMvc();
services.AddSwaggerGen();
services.AddMemoryCache();
var container = new Container();
container.Configure(config =>
{
config.AddRegistry<DefaultRegistry>();
config.Populate(services);
});
services.Configure<JsonConfiguration>(Configuration.GetSection("settings"));
services.Configure<SharedVariables>(Configuration.GetSection("sharedVariables"));
services.Configure<Environments>(Configuration.GetSection("environments"));
return container.GetInstance<IServiceProvider>();
}
I couldn’t see anything wrong with it, and I looked all over the internet to see what I was doing wrong. At first I thought the Configuration Builder didn’t support Lists/IEnumerable, however I found posts from over a year ago claiming it did, so I was stumped.
After a while of commenting out code, I found my StructureMap configuration was breaking the IOptions from picking up the correct config (which is worrying because I wasn’t doing anything crazy).
In the end I found the ordering of my ConfigureServices
was very important – you need to ensure you have done all of your service setup before setting up your StructureMap instance.
After figuring that out, I simply moved the configuration lines above any StructureMap setup and tadah – everything is now fine. My method now looks like this:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddOptions();
services.AddMvc();
services.AddSwaggerGen();
services.AddMemoryCache();
services.Configure<JsonConfiguration>(Configuration.GetSection("settings"));
services.Configure<SharedVariables>(Configuration.GetSection("sharedVariables"));
services.Configure<Environments>(Configuration.GetSection("environments"));
var container = new Container();
container.Configure(config =>
{
config.AddRegistry<DefaultRegistry>();
config.Populate(services);
});
return container.GetInstance<IServiceProvider>();
}
I hope this can help someone