I created a asp.net core 2.1 API project (not inside service fabric) in that if I add this code to the ValuesController.cs I am able to retrieve the config from appsettings.json
private IConfiguration configuration;
public ValuesController(IConfiguration iConfig)
{
configuration = iConfig;
}
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
string dbConn = configuration.GetSection("MySettings").GetSection("DbConnection").Value;
return new string[] { "value1", "value2" };
}
The same similar project I create a stateless asp.net Core API Service fabric project this does not work by default I have to add specific reference to appsetting.json. When I look at the project they both look very similar. Is this the right approach? such is not needed in non service fabric project.
return new WebHostBuilder()
.UseKestrel()
.ConfigureAppConfiguration((builderContext, config) =>
{
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.ConfigureServices(
services => services
.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
Inside Service Fabric I don't use appsetings at all. I follow the approach where I keep every setting for all services in one place which is ApplicationPackageRoot/ApplicationManifest.xml inside Service Fabric project. So for example if I have two services, ApplicationManifest can look like this:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="TestAppType"
ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="Environment" DefaultValue="" />
<Parameter Name="TestWebApi_InstanceCount" DefaultValue="" />
<Parameter Name="TestServiceName" DefaultValue="TestService" />
<Parameter Name="TestService_InstanceCount" DefaultValue="" />
</Parameters>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="TestServicePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides>
<ConfigOverride Name="Config">
<Settings>
<Section Name="General">
<Parameter Name="Environment" Value="[Environment]" />
<Parameter Name="TestServiceName" Value="[TestServiceName]" />
</Section>
</Settings>
</ConfigOverride>
</ConfigOverrides>
</ServiceManifestImport>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="TestWebApiPkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides>
<ConfigOverride Name="Config">
<Settings>
<Section Name="General">
<Parameter Name="Environment" Value="[Environment]" />
</Section>
</Settings>
</ConfigOverride>
</ConfigOverrides>
</ServiceManifestImport>
<DefaultServices>
<Service Name="TestService" ServicePackageActivationMode="ExclusiveProcess">
<StatelessService ServiceTypeName="TestServiceType" InstanceCount="[TestService_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
<Service Name="TestWebApi" ServicePackageActivationMode="ExclusiveProcess">
<StatelessService ServiceTypeName="TestWebApiType" InstanceCount="[TestWebApi_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
I just put there definitions of the parameters used for the application, and specific configs for each service. Next step is to prepare application parameter files for each environment where you put real values, for example Dev.xml:
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="fabric:/TestApp" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="Environment" Value="Dev" />
<Parameter Name="TestWebApi_InstanceCount" Value="1" />
<Parameter Name="TestServiceName" Value="TestService" />
<Parameter Name="TestService_InstanceCount" Value="-1" />
</Parameters>
</Application>
During the application deploy you just specify which file you want to use. Now to use config inside the service you need to modify PackageRoot/Config/Settings.xml file for each service:
<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Section Name="General">
<Parameter Name="Environment" Value=""/>
<Parameter Name="TestServiceName" Value=""/>
</Section>
</Settings>
Again you don't specify values here, they will be taken from the ApplicationManifest. You just tell which one you want to use for specific service.
Now the code. I've created helper class to retrieve config values:
public class ConfigSettings : IConfigSettings
{
public ConfigSettings(StatelessServiceContext context)
{
context.CodePackageActivationContext.ConfigurationPackageModifiedEvent += this.CodePackageActivationContext_ConfigurationPackageModifiedEvent;
UpdateConfigSettings(context.CodePackageActivationContext.GetConfigurationPackageObject("Config").Settings);
}
private void CodePackageActivationContext_ConfigurationPackageModifiedEvent(object sender, PackageModifiedEventArgs<ConfigurationPackage> e)
{
this.UpdateConfigSettings(e.NewPackage.Settings);
}
public string Environment { get; private set; }
public string TestServiceName { get; private set; }
private void UpdateConfigSettings(ConfigurationSettings settings)
{
var generalSectionParams = settings.Sections["General"].Parameters;
Environment = generalSectionParams["Environment"].Value;
TestServiceName = generalSectionParams["TestServiceName"].Value;
}
}
public interface IConfigSettings
{
string Environment { get; }
string TestServiceName { get; }
}
This class also have an event subscription which will update config if it was changed while service was running.
What's left is to initialize your ConfigSettings
with the service context during the startup and add it to the builtin ASP.NET CORE Container so you can use it in other classes:
.ConfigureServices(services => services
.AddSingleton<IConfigSettings>(new ConfigSettings(serviceContext)))
EDIT:
Once you have your config in asp.net core IoC Container you can use it by constructor injection like this:
public class TestClass
{
private readonly IConfigSettings _config;
public TestClass(IConfigSettings config)
{
_config = config;
}
public string TestMethod()
{
return _config.TestServiceName;
}
}