Checking App Settings at Startup
This article provides a comprehensive sample demonstrating how to effectively utilize app settings in ASP.NET Core applications.
Problem Statement
In the realm of application development, managing settings efficiently can be a pivotal but often overlooked aspect, especially when collaborating with team members. Imagine a scenario where you or your colleagues add or remove settings during development, such as passwords, connection strings, or keys. These sensitive pieces of information should never find their way into your source code control system.
However, a common occurrence is that someone adds a new setting essential for a feature without communicating it to other team members. Consequently, you might encounter unexpected exceptions or peculiar behavior within your application, leading to time-consuming investigations.
Consider this familiar code snippet:
string openAIKey = Environment.GetEnvironmentVariable("OpenAIKey");
This pattern, while prevalent, is both frustrating and risky when employed within teams.
Solution
To mitigate such issues effectively, I strongly advocate for implementing the following practices:
- Define Settings in a Dedicated Class
using System.ComponentModel.DataAnnotations;
namespace Oliver.Tools.Copilots
{
public class OpenAISettings
{
public const string Key = "OpenAISettings";
[Required(ErrorMessage = "OpenAIKey required")]
public required string OpenAIKey { get; set; }
[Required(ErrorMessage = "OpenAIEndpoint required")]
public required string OpenAIEndpoint { get; set; }
}
}
- Configure Settings at Startup in Program.cs
IServiceCollection services = builder.Services;
IConfigurationSection? openAISettings = builder.Configuration.GetSection(OpenAISettings.Key);
services
.Configure<OpenAISettings>(openAISettings)
.AddOptionsWithValidateOnStart<OpenAISettings>()
.ValidateDataAnnotations();
- Run the application
Encountering an exception at the application’s start is both beneficial and intentional.
The sooner the better an exception is thrown, the earlier you can fix a problem. It is getting harder when you need to search late in the development process for a missing setting, somewhere hidden in the some code.
- Include Settings in your local appsettings.json File
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"OpenAISettings": {
"OpenAIKey": "1234567890987654321",
"OpenAIEndpoint": "https://youropenaiendpoint.openai.azure.com/"
},
...
}
Even though settings are not case-sensitive by default, any minor typos will result in exceptions.
- Additional Perk: Dependency Injection
This pattern facilitates effortless dependency injection, allowing settings to be readily injected into other classes.
namespace DataWebApp.Controllers
{
[ApiController]
[Route("[controller]")]
public class ChatController : ControllerBase
{
private readonly OpenAISettings _mySettings;
public ChatController(IOptions<OpenAISettings> mySettings)
{
_mySettings = mySettings.Value;
}
...
}
}
In Conclusion
Adopting this recommended approach not only streamlines your development process but also saves invaluable time that would otherwise be spent scouring through codebases in search of elusive settings.
About the Author / Oliver Scheer
Meet Oliver, a Principal Software Engineer at Medialesson, boasting over 25 years of software development expertise across real and challenging customer projects. With 17 years of experience at Microsoft as both an Evangelist and Software Engineer, Oliver's focus lies in .NET, DevOps, Developer Experiences, and Cloud technologies. For more about Oliver, visit his website or LinkedIn profile.