appsettings.json and azure function by timer - c#

I am pretty a new at azure function development
and I a not really understand how configuration for azure function, especially for local development
I need to set up some parameters at configuration and use them at my code
I have appsettings.json and local.settings.json
I added IConfiguration configuration as parameter to constructor to some my class
and try to get value by calling
_configuration["MyVar"]
but values are always null. (like it not read appsettings.json)
that is the best practice to get/set some parameters values for local test and use them after on azure side.

You can set your configuration values in local.settings.json for debugging and in the Function AppSettings in Azure Portal for when it's deployed. If you want to use a custom appsettings file, you need a FunctionStartup class.
You won't be able to configure the trigger bindings in the appsettings file, you'll have to use the Function AppSettings for that. Please see this StackOverflow post for more details.

Recommended way to read App settings in Azure functions(in App Service) is:
var value = Environment.GetEnvironmentVariable("your_key_here");
Check out this article for detailed explanation: Azure — Reading application settings in Azure Functions (ASP.NET Core)

Related

How can I get multiple blobs out of an Azure Function?

I'm coding a C# function which is triggered by the upload of a blob. I would like to read another file in the container. How would the input binding bring the second blob?
public static async Task Run([BlobTrigger("csv/{name}.csv", Connection = "StorageConnectionAppSetting")]Stream myBlob, string name, ILogger log)
In addition to this question, how can I reference values from the local.settings.json in my code? I'm able to reference the "StorageConnectionAppSetting" on the input binding but I'm not sure how to do the same for portions of my code where I'm creating clients using APIKEYs.
Thanks!
A blob-trigger can be a single blob, but you can add an input binding to your function. In this case you can add an input binding to CloudBlobContainer by adding a reference to the storage SDK, and then read any blobs in that container.
https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-blob-input?tabs=csharp#usage.
Another option would be not to use input binding and read the container and its contents the way you would normally do using storage SDK. You will need to add reference to Microsoft.Azure.Storage.Blob in both the cases.
For app settings you can use System.Environment.GetEnvironmentVariable("APIKEY");, assuming APIKEY is your customer setting. Remember, local.settings.json will only be local and you will need to set these values in Azure either via Azure Portal or your CI/CD pipeline via and ARM template.
You can also use Azure functions dependency injection and inject configuration. Check the section Working with options and settings at https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection#working-with-options-and-settings

What's the correct way to set Blazor Webassembly environment?

My goal is to be able to change the environment name from configuration file. If the server is configured for X, then the client should also use X environment.
You know, in ASP.NET we can use launchSettings.json to configure IIS server to Development, and the "real" server which is published to Production. The WASM client should see the same configuration. I would like to configure the environment only here to reduce the resik of forgetting something when publishing the server.
There are multiple articles describing Blazor environments, but I'm confused setting it up correctly.
To get the environment saw by the client, I added this line to the Client/Program.cs file:
Console.WriteLine("Using environment " + builder.HostEnvironment.Environment);
Experiemets:
If I change the Server/launchSettings.json/profiles/IIS Express/environmentVariables/ASPNETCORE_ENVIRONMENT from Development to Production, the website simply won't load (returns 404).
In some other cases, ASPNETCORE_ENVIRONMENT is just ignored / not accessible by the client.
When running an app locally, the environment defaults to Development. When the app is published, the environment defaults to Production.
That's true sometimes for me, but not always. Some cases the environment is Production even if I run locally.
Blazor.start({ environment: "Staging" }); described in this article has no effect. Also that takes a string, how could I pass the server side config variable's value?
Using web.config, I can always overwrite the environment name. There's two problems:
Why maintain another configuration file? There's already launchSettings.json, and the server will depend on that file. As far as I know, I can't reference other settings from the web.config file.
It's really not the blazor-environment header which controls the environment name. Why?
Remove web.config
In Server/Startup.cs, add:
app.Use(async (context, next) =>
{
context.Response.Headers.Add("blazor-environment", env.EnvironmentName);
await next.Invoke();
});
In Chrome DevTools, I can see the value of the header is indeed Development. But the client prints Production.
If the header is ignored, why would I set it in web.config? It it's set, but the clinet WASM project doesn't read the header, how else it knowns the name? Is the referenced Blazor WASM JavaScript file changed, the environment name is compiled into that?
There is also Client/launchSettings.json generated, which seem to be completely ignored.
There are at least 10 ways described to get the environment name. Some use appsettings.json (which is separately download, or IWebAssemblyHostEnvironment, or IConfiguration, or Razor component ect. All I want is to read the global environment name in C# code parts.
I guess this chaos comes from the fact Blazor was changed in the recent years. I'm a bit lost. Which one should I use? Which should always work? Can I get rid of the need to change both web.config and launchSettings.json?
If your wasm is hosted by an asp.net core app, the call to
app.UseBlazorFrameworkFiles();
should add the headers required automatically. You can check this by looking at the headers passed back in a network monitor for the blazor.boot.json file, which is the request that blazor uses to read the blazor-environment header from.
Note that in the sample where you manually added that header, if you didn't add it before the 'AddStaticFiles', that header probably would have been added to your index page, but NOT the blazor.boot.json file, so it would have had no effect.
One other thing to take note of is that the call to app.UseBlazorFrameworkFiles() MUST go before app.UseStaticFiles(). That one tripped me up, hopefully that helps anyone who comes in here searching for an answer :)
ref:
code where blazor wasm reads header: https://github.com/dotnet/aspnetcore/blob/5fed81205944c528cbf7bb3a4ce369ca37bd3676/src/Components/Web.JS/src/Platform/BootConfig.ts#L29
I'm using Blazor Server and not Blazor Web Assembly, but I'm thinking you can do what I do and just set the environment in the ASPNETCORE_ENVIRONMENT variable. When debugging in Visual Studio, set the variable in the launchSettings.json file (note if you have multiple profiles such as IIS Express and YourProject, the variable should exist for each profile (best to keep the value for the variable the same)). When running the app on a server, the ASPNETCORE_ENVIRONMENT variable should exist as an environment variable on the server (VM or physical on-prem etc) or for Azure Web Site (aka Azure App Service) as a variable under Settings->Configuration. Note for environment variables you typically have to log out the runtime user and restart the service before the new value will be read.
If you have code such as env.IsDevelopment(), env.IsStaging(), or env.IsProduction, you will need to use the standard environment names (Development, Staging, and Production).
For Blazor Server, inside Program.cs CreateHostBuilder method where you call Host.CreateDefaultBuilder(args).CongigureWebHostDefaults(webHostBuilder =>
you can read the environment variable this way:
ConfigurationBuilder = new ConfigurationBuilder()
.AddEnvironmentVariables("ASPNETCORE_");
const string aspnetCoreEnv = "ASPNETCORE_ENVIRONMENT";
var environmentName = Environment.GetEnvironmentVariable(aspnetCoreEnv);
Now add the appropriate appsettings file containing the environment name:
ConfigurationBuilder.AddJsonFile($"appsettings.{EnvironmentName}.json", true, true);
var configuration = ConfigurationBuilder.Build();
webHostBuilder.UseConfiguration(configuration);
var hostBuilderEnvironmentSetting = webHostBuilder.GetSetting(WebHostDefaults.EnvironmentKey);
if (string.IsNullOrEmpty(hostBuilderEnvironmentSetting))
webHostBuilder.UseSetting(WebHostDefaults.EnvironmentKey, EnvironmentName);
If you are using Startup.cs, then you can use constructor injection so you can access the environment within Startup:
public Startup(IConfiguration configuration, IWebHostEnvironment hostingEnvironment)
If Blazor Web Assembly configures differently, maybe you can still achieve the equivalent logic to make it load the appsettings that match the environment.
With this approach, I have not encountered issues where the app does not identify the environment properly. I don't have a web.config file so haven't needed to maintain values there. The only "won't load" issue I have hit was in Azure where my publish config specified a "Microsoft Identity Platform" which references an Azure App Registration and that app registration didn't have under Redirect URIs a Web Platform with URI for my environment-specific app service.

Can I configure a default value for an Azure Functions binding expression?

I want to simplify deployment of my Azure Functions v3 project as much as possible.
As an example, take this function, which uses a binding expression to refer to the DoTheThingSchedule appsetting:
[FunctionName("DoTheThing")]
public async Task Run([TimerTrigger("%DoTheThingSchedule%")]TimerInfo timer)
{
// do the thing
}
For local development I can configure a value for DoTheThingSchedule in local.settings.json, but I haven't found a way to configure a default value in production, which means I'll always have to explicitly configure this setting in Azure.
Does anyone know of a way to work around this?
Azure needs you to add settings in configuration settings in azure. And it will not upload local.settings.json file to azure. But if you are using VS to publish, you can set the settings before publish:

ConfigurationManager on Azure environment

I use this below code to read configuration. This code is used in global.asax Application_Start method.
var showAllMethodSetting = ConfigurationManager.AppSettings["ShowAllMethodsInSwaggerDocs"];
bool showAllMethods;
if (!bool.TryParse(showAllMethodSetting, out showAllMethods) || !showAllMethods)
{
... code ...
}
It works great in my local configuration (appSetting.config), but when I push my code to Azure. It not works.
Entry ShowAllMethodsInSwaggerDocs is visible in Azure panel with proper value (I add node in *.csdef and *.cscfg), but this value is not used. Why? Maybe should I use other class than ConfigurationManager?
You need to use the nuget package Microsoft Azure Configuration Manager to pick up the configuration settings both in the portal, and in your web.config.

Dynamically change azure configuration (.cscfg) values

I'm having azure worker role project. below is a code from my configuration (.cscfg).
c# (FLAG = 1;)
Through c# code i want to change this value.
Is there any way for dynamically changing value of an azure service configuration?
Please instruct me how to do it.
Simple answer is that you can't change the value of just one setting through code as RoleEnvironment class only exposes a Get method and there's no Set method.
A convoluted approach would be to invoke Service Management API, read the configuration settings file using Get Deployment operation, change the XML file and the call Change Deployment Configuration operation. Not sure how this would work out if you're changing the configuration from the same role though.

Categories