Reputation: 514
I have a json Config file which I would like to read from inside the Azure function. We have by default localsettings.json file but I need a one more Json config file to read in my function code. Whats the best way, till now for my other projects I was able to read by below code but this wont work from inside Azure function.
var builder = new ConfigurationBuilder()
.SetBasePath(Path.Combine(Root))
.AddJsonFile("DataFileConfiguration.json", optional: false);
var config = builder.Build();
var tableStorageOutput = new TableStorageConfiguration();
config.GetSection("TableStorageRule").Bind(tableStorageOutput);
Upvotes: 2
Views: 7305
Reputation: 1368
Oh boy this is long, I put a TL;DR:POC at bottom
This took me a while to figure out when I was working on it, so I decided to create a small guide about this.
Create the metadata file: We call it appsettings.json
just because we all worked in C# web APIs before and we were used to, but you can call it whatever you want.
Make sure that this file is always copied when building the solution. Right click on the file over Solution Explorer
=> Properties
=> Copy to Output Directory
=> Copy always
Create a class to strongly-type your appsettings json file
public class AppSettings
{
public string SomeValue { get; set; }
}
Startup.cs
file in your .csproj
that inherits from FunctionsStartup
[assembly: FunctionsStartup(typeof(FunctionApp.Startup))]
namespace FunctionApp
{
public class Startup: FunctionsStartup
{
private IConfigurationRoot Config = null;
private IConfigurationRoot FunctionConfig(string appDir) =>
Config ??= new ConfigurationBuilder()
.AddJsonFile(Path.Combine(appDir, metaDataFileName), optional: false, reloadOnChange: true)
.Build();
}
}
Thanks to Anthony Brenelière
for that. Reference
Implement the Configure
method. This is where you will bootstrap all your DI services, for example:
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddTransient<IService, SomeService>();
//some other services
}
Inside your Configure
method define your IOptions
as:
builder.Services.AddOptions<AppSettings>()
.Configure<IOptions<ExecutionContextOptions>>((settings, exeContext) =>
FunctionConfig(exeContext.Value.AppDirectory).Bind(settings));
Now you can finally access to your data as:
public class AzureFunction
{
private readonly AppSettings AppSettings;
public AzureFunction(IOptions<AppSettings> appsettings)
{
AppSettings = appsettings.Value;
}
[FunctionName("AzureFunction")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
ILogger log)
{
var result = AppSettings.SomeValue;
return new OkObjectResult(result);
}
}
Bonus track: As far as I know, there is no elegant way to inject an appsettings.json file in the constructor of the startup class as in web APIs.
//we cannot do this in azure function (yet)
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
So, how can I access, for example to the SQL ConnectionString? I need it when stepping into Configure
method so I can register the service somewhat like this:
builder.Services.AddDbContext<SqlDbContext>(
options => options.UseSqlServer(//howww???, I don't want to hard code it));
Well, the only way that I personally could make it work is:
For local development: Defining it in the local.settings.json
as
"ConnectionStrings": {
"SqlConnectionString": "some connectionstring"
}
And in the Startup
class access it through Environment.GetEnvironmentVariable
Environment.GetEnvironmentVariable("ConnectionStrings:SqlConnectionString")
For Azure Web Apps:, If you are you are deploying to an App Service, the connection string should be defined on azure portal
=> your azure function
=> settings\configuration
with the same key as the json file to be able to work on both environments (local/cloud) at the same time.
But wait, there is more:
Azure App services require you to define the connectionstring in azure portal as per the image above, no biggie right? It makes some sense that they command how to set things up. After all, they will only set an environment variable in the app service with the key provided, in my example SqlConnectionString
.
No, they configure your connectionstring with the key SQLCONNSTR_{name}
. You can check this, if you go to the kudu console
in azure over advance tools
and do a >cmd set
to list all the environment variables of your app service.
Big shout out to @johnwc for that pointer
TL;DR: I created a small POC to achieve this here: link
Upvotes: 1
Reputation: 763
Right click your 'DataFileConfiguration.json' file in the solution explorer -> Properties -> Copy to output folder = 'Copy always'
Upvotes: 2