Azure Durable Function AppSettings - configuration

I'm trying to create an azure durable function but it's very difficult to find some normal guides on this subject. I've setup the DI and I try to read the settings of the function but it crashes
I have setup an Azure Function project in VS 2019 and added a Durable Orchestrator Function Template. I removed all the "static" references from the class and all seem to work fine until I add the configurationbuilder in the startup file
Can anyone explain to me how this should work or give some guidance, where to find some explanation of the configuration of a durable functions ? What should I have in the host.json , local.settings.json and how this changes be when I publish it on the portal ?
My case is this. The startup file looks like this
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
[assembly: FunctionsStartup(typeof(DurableFunctions.Startup))]
namespace DurableFunctions
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
var settings = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
}
}
}
The host.json is like this
{
"version": "2.0"
}
The local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}
And the error I get when I start the debugger is this
This is output:
[11/8/2019 10:29:04 AM] A host error has occurred during startup operation '8b80bc94-2b98-408b-895f-c5697430acfd'.
[11/8/2019 10:29:04 AM] Microsoft.Azure.WebJobs.Extensions.DurableTask: Value cannot be null.
[11/8/2019 10:29:04 AM] Parameter name: hostConfiguration.
Value cannot be null.
Parameter name: provider

You want to instead override the ConfigureAppConfiguration method in your FunctionStartup class (https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection#customizing-configuration-sources).
The following example takes the one provided in the documentation a step further by adding user secrets.
public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
{
FunctionsHostBuilderContext context = builder.GetContext();
builder.ConfigurationBuilder
.SetBasePath(context.ApplicationRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
.AddJsonFile($"appsettings.{context.EnvironmentName}.json", optional: true, reloadOnChange: false)
.AddUserSecrets(Assembly.GetExecutingAssembly(), true, true)
.AddEnvironmentVariables();
}
By default, configuration files such as appsettings.json are not automatically copied to the Azure Function output folder. Be sure to review the documentation (https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection#customizing-configuration-sources) for modifications to your .csproj file. Also note that due to the way the method appends the existing providers it is necessary to always end with .AddEnvironmentVariables().
A deeper discussion on configuration in an Azure Function can be found at Using ConfigurationBuilder in FunctionsStartup

Did you get a response to this?
Did you try adding the local settings from the json, before the Environment Variables?
var config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
// This gives you access to your application settings in your local development environment
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: false)
.AddJsonFile("secret.settings.json", optional: true, reloadOnChange: false)
// This is what actually gets you the application settings in Azure
.AddEnvironmentVariables()
.Build();
I am having trouble when I deploy, I have set up a variable group yet they are not being picked up.

Related

How to load app configuration from appsettings.json in MAUI startup?

I would need to retrieve my app settings from an appsettings.json file in a MAUI application.
I tagged it a MauiAsset generation action, and I can see it in the assets directory of of the generated apk.
It doesn't seem to be available in ConfigureAppConfiguration and no AddJsonFile extension exists to add it in the application builder.
Should I use another generation action?
What is the good way to retrieve it?
public void Configure(IAppHostBuilder appBuilder)
{
appBuilder
.ConfigureAppConfiguration((app, config) =>
{
// I should be able to work with appsettings here
})
.ConfigureServices(svcs =>
{
})
.UseMauiApp<App>();
}
It looks like the ConfigureAppConfiguration was just added with this PR a couple of days ago. It will probably show up for the next release.
If you really need it now you could add it as an embedded resource and do the deserialization from JSON yourself. If you could wait a bit longer you probably want to do that.
It's possible to get the usual host builder by using the MauiAppBuilder.Host getter.
var builder = MauiApp.CreateBuilder();
builder
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
})
.UseMauiApp<App>()
.Host
.ConfigureAppConfiguration((app, config) =>
{
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.ConfigureServices((ctx, svcs) =>
{
})
.ConfigureLogging(logging =>
{
logging.AddSerilog();
});
To get app location and appsetings path, use the following:
Assembly CallingAssembly = Assembly.GetEntryAssembly();
Version VersionRuntime = CallingAssembly.GetName().Version;
string AssemblyLocation = Path.GetDirectoryName(CallingAssembly.Location);
string ConfigFile = Path.Combine(AssemblyLocation, "appsettings.json");

Add custom section to .NET Core local.settings.json

I'm writing my first Azure function (based on .NET Core 2.x), and I'm struggling to extend the app settings with my custom mapping table.
I have a file local.settings.json, and I have tried to extend it with a "custom" config section that contains a few "key/value" pairs - something like this:
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
... (standard config settings) ...
},
... (more default sections, like "Host" and "ConnectionStrings")
"MappingTable" : {
"01" : "Value1",
"02" : "Value2",
"03" : "Value3",
"else" : "Value4"
}
}
I get the IConfiguration injected into my worker class via constructor injection, and it works just fine for the "basic" default values stored in the "Values" section:
public MyWorker(IConfiguration config)
{
_config = config;
string runtime = _config["FUNCTIONS_WORKER_RUNTIME"]; // works just fine
// this also works fine - the "customSection" object is filled
var customSection = _config.GetSection("MappingTable");
// but now this doesn't return any values
var children = customSection.GetChildren();
// and trying to access like this also only returns "null"
var mapping = customSection["01"];
}
I'm stuck here - all the blog post and articles I find seem to indicate to do just this - but in my case, this just doesn't seem to work. What am I missing here? I'm quite familiar with the full .NET framework config system - but this here is new to me and doesn't really make a whole lot of sense just yet......
I have also tried to move the entire MappingTable section to appSettings.json - but that didn't change anything, I'm still getting back only null when trying to access my custom config section's values....
Thanks!
Update: all the suggested ways of doing this work just fine with a standard ASP.NET Core 2.1 web app - but in the Azure function, it's not working. Seems like code in an Azure Function is treating configuration differently than a regular .NET Core code base ...
I did something similar using .net core 3.0
local.settings.json
{
"AppSettings":{
"MappingTable" : {
"01" : "Value1"
}
}
}
Reading appsettings:
private void AppSettings()
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
var 01 = config["AppSettings:MappingTable:01"];
}
In the Azure portal, you need to add this as an application setting.
In your Function App -> Configuration -Application Settings -> New Application setting
Name:AppSettings:MappingTable:01
Value:Value1
A R G H ! ! !
I knew it - such a stupid little mistake - but with rather massive consequences.....
In my startup class, I had this code (plus some more):
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddHttpClient();
var config = new ConfigurationBuilder()
.SetBasePath(Environment.CurrentDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
.....
}
}
but what was missing is this one line of code after the call to .Build() above:
builder.Services.AddSingleton<IConfiguration>(config);
Somehow, the settings in the Values section of local.settings.json were present and accessible, but any custom config sections weren't.
Adding this one line has solved my problem - now I can easily read the MappingTable from my local.settings.json (or appsettings.json) file and use it in my code.

Startup.cs error (ASP.Net Core configuration)

I am trying to set up an ASP.Net Core application to read in configuration settings from a json file. I am using VS2015 and .NetCore 1.0 (with .Net Core Tools preview 2). I am having problems getting a simple piece of boiler plate code to compile.
I am using the following code, which was published at
http://asp.net-hacker.rocks/2016/03/21/configure-aspnetcore.html
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
if (env.IsDevelopment())
{
// This will push telemetry data through Application Insights
// pipeline faster, allowing you to view results immediately.
builder.AddApplicationInsightsSettings(developerMode: true);
}
Configuration = builder.Build();
}
However, the IDE/compiler complains that 'the name "Configuration" does not exist in the current context' (last line of code). The only suggestion from the IDE is to include Microsoft.Extensions.Configuration. However this is a namespace which does not contain an object or property named "Configuration".
In addition 'AddApplicationInsightsSettings' fails with does IConfigurationBuilder not contain a definition for AddApplicationInsightsSettings and no extension method AddApplicationInsightsSettings accepting a first argument of type IConfigurationBuilder could be found
Any suggestions please ?
Thanks
Simply add Configuration property to your Startup class, tutorial has missed this 'step':
public IConfigurationRoot Configuration { get; set; }
ConfigurationBuilder.Build() method just returns instance of IConfigurationRoot, that you should save, if need to get settings further in Startup class (in ConfigureServices method for example).
Regarding second error, looks like you didn't add the Application Insights dependency:
{
"dependencies": {
"Microsoft.ApplicationInsights.AspNetCore": "1.0.0"
}
}

Configuration of asp.net core using settings

I'm evaluating asp.net core and .net core and I'm not yet sure about some things. In the past it was possible to configure many components using the web.config out of the box.
To name some examples:
There was the membership-provider and I could implement many providers but I was able ton configure later which provider should be used. This was dependend of the use-case. Now I should use asp.net identity - but I can only find configurations that are performed in sourcecode.
Same for authentication. I can define "CookieAuthentication" and have to set the name, loginpath or the timeout within sourcecode. In the past I was able to set timeout, etc... via web.config.
Is there any way to configure partially these things out of the box from a config-file? Or is this not supported anymore and I have to implement this configuration on my own? In the past this was a really comfortable way.
In ASP.NET Core, Web.config file is used ONLY for IIS configuration, you cannot use it for application configuration, but there are new, better, more flexible configuration options that you can use.
There are multiple configuration sources that you can use, but in this example I'm using json. These examples are from working code in my SimpleAuth project.
You can configure things in startup from configuration files.
First you add a config file in json format that maps to your class. You can see my example class here, and the json file it maps from here
builder.AddJsonFile("simpleauthsettings.json", optional: true);
Then, in the ConfigureServices method you configure your class to be wired up from the config system as shown
services.Configure<SimpleAuthSettings>(Configuration.GetSection("SimpleAuthSettings"));
Then you add an IOptions accessor of your class to the method signature of the Configure method in the Startup.cs
The Dependency Injection will inject it into that method for you so you can use it there to configure things. Specifically I'm setting the cookie authentication scheme and name from my settings object.
The noteworthy part is that you can add whatever you want to the Configure method signature, and as long as it is something that has been registered in the ConfigureServices method, the DI will be able to inject it for you.
public class Startup
{
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
// this file is the custom configuration file to hydrate my settings from
builder.AddJsonFile("simpleauthsettings.json", optional: true);
....
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; set; }
public void ConfigureServices(IServiceCollection services)
{
....
services.Configure<SimpleAuthSettings>(Configuration.GetSection("SimpleAuthSettings"));
....
}
// note that the DI can inject whatever you need into this method signature
// I added IOptions<SimpleAuthSettings> authSettingsAccessor to the method signature
// you can add anything you want as long as you register it in ConfigureServices
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
IOptions<SimpleAuthSettings> authSettingsAccessor
)
{
...
// Add cookie-based authentication to the request pipeline
SimpleAuthSettings authSettings = authSettingsAccessor.Value;
var ApplicationCookie = new CookieAuthenticationOptions
{
AuthenticationScheme = authSettings.AuthenticationScheme,
CookieName = authSettings.AuthenticationScheme,
AutomaticAuthenticate = true,
AutomaticChallenge = true,
LoginPath = new PathString("/Login/Index"),
Events = new CookieAuthenticationEvents
{
//OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
}
};
app.UseCookieAuthentication(ApplicationCookie);
// authentication MUST be added before MVC
app.UseMvc();
}
}

OSGi Declarative Services and Config Admin

I'm writting bundle with declarative services usage. For configuration I'm using properties in DS declaration. Those props can be normally changed by Config Admin, but they are not persisted. After container restart, component has default values.
I'am using Config admin like this:
Configuration c = configurationAdmin.getConfiguration(UserAgent.SERVICE_PID, null);
System.out.println(c.getProperties()); // every time is null!
Dictionary props = new Hashtable();
props.put(UserAgent.PROPERTY_PORT, 5555);
c.update(props);
and in component I have:
// ...
#Modified
public void updated(ComponentContext context) {
config = context.getProperties();
init();
}
#Activate
protected void activate(ComponentContext context) {
config = context.getProperties();
init();
}
//...
I'm using Felix, properties file is stored in cache
service.bundleLocation="file:bundles/cz.b2m.osgi.phonus.core_1.0.0.SNAPSHOT.jar"
service.pid="cz.b2m.osgi.phonus.sip"
port=I"5555"
But after restart isn't loaded. What I'm doing wrong? Thanks for all tips.
Problem was in Pax Runner which every restart (clean) erased the data folder of Config Admin bundle.
To make sure that Pax Runner does not clear the data, you can use the --usePersistedState=true flag.