Developers building conventional .NET desktop solutions typically store information needed while running an application using My.Settings, which provides read/write capabilities. Here, learn how to use a Json file to store read-only information while discarding write back to the Json file. If there is a need to modify the Json file consider using Microsoft’s System.Text.Json or Newton.Json libraries to save modifications.

Several of the projects in the GitHub repository are .NET 5 along with several projects using Entity Framework Core. When building the projects and one or more fail because the developer machine does not have .NET 5 and/or Entity Framework Core consider unloading those projects.

Working with My.Setting

Creating and working with settings in Visual Studio, open project properties to the Settings tab. From here see Microsoft documentation.

For the above, Visual Studio adds these properties to app.config which after building a project names the file project name.exe.config.

<?xml version="1.0" encoding="utf-8" ?>
        <sectionGroup name="userSettings"
                      type="System.Configuration.UserSettingsGroup, System, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="AppSettingsMySettings.My.MySettings"
                     type="System.Configuration.ClientSettingsSection, System, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089"
                     allowExeDefinition="MachineToLocalUser" requirePermission="false" />
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
            <setting name="ConnectionString" serializeAs="String">
                <value>Data Source=DevServer;Initial Catalog=NorthWindAzure;Integrated Security=True</value>
            <setting name="WindowsAuthentication" serializeAs="String">

Access these settings as follows

Rolling your own loader

As developer become seasoned, they learn rolling their own method to store and read setting is more reliable and provides more control while if the developer does not code in specific functionality it's not there.

Using My.Setting properties from the first example.
<?xml version="1.0" encoding="utf-8"?>
        <section name="SettingsConfig" type="BasicAppConfig.AppSettngsLoader, BasicAppConfig" />
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
        <ConnectionString>Data Source=DevServer;Initial Catalog=NorthWindAzure;Integrated Security=True</ConnectionString>

AppSettingsLoader is a class in a sample project (included in the source code) which requires a reference to System.Configuration.

01.Imports System.Configuration
02.Imports System.Xml
03.Imports System.Xml.Serialization
05.Public Class AppSettngsLoader
06.    Implements IConfigurationSectionHandler
08.    Public Function Create(parent As Object, configContext As Object, section As XmlNode) As Object _
09.        Implements IConfigurationSectionHandler.Create
11.        If section Is Nothing Then
12.            Throw New ArgumentNullException($"XMLNode passed in is null.")
13.        End If
15.        Dim type = AppDomain.CurrentDomain.GetAssemblies().
16.                SelectMany(Function(assembly) assembly.GetTypes()).
17.                FirstOrDefault(Function(itemType) itemType.Name = section.Name)
19.        If type Is Nothing Then
20.            Throw New ArgumentException($"Type with name {section.Name} couldn't be found.")
21.        End If
23.        Dim ser As New XmlSerializer(type, New XmlRootAttribute(section.Name))
25.        Using reader As XmlReader = New XmlNodeReader(section)
26.            Return ser.Deserialize(reader)
27.        End Using
29.    End Function
31.End Class

BasicAppConfig is the namespace for the current project which means if the project namespace changes this needs to change too.

A concrete class for storing the two properties in the configuration file.
1.Public Class SettingsConfig
2.    Public Property ConnectionString() As String
3.    Public Property WindowsAuthentication() As Boolean
5.    Public Overrides Function ToString() As String
6.        Return $"{ConnectionString}, {WindowsAuthentication}"
7.    End Function
8.End Class

To get the properties.
Dim config = DirectCast(ConfigurationManager.GetSection("SettingsConfig"), SettingsConfig)

Then for instance, get the ConnectionString.

Using appSettings in app.config

Another method is using appSettings section in app.config.

    <add key="ConnectingString" value="Data Source=.\SQLEXPRESS;Initial Catalog=NorthWind2020;Integrated Security=True" />

Example usage in a DbContext for a Entity Framework Core class.
  • Line 10 variable is for the connection string from app.config
  • Line 25 uses ConfigurationHelper class to read the connection string
  • Line 29 assigns the connection string to the DbContextOptionsBuilder which provides Entity Framework what is needed to work with data.

01.Imports System.Configuration
02.Imports Contexts.Configurations
03.Imports Microsoft.EntityFrameworkCore
04.Imports Models
06.Namespace Contexts
07.    Partial Public Class NorthWindContext
08.        Inherits DbContext
10.        Private _connectionString As String
12.        Public Sub New()
14.        End Sub
16.        Public Sub New(options As DbContextOptions(Of NorthWindContext))
17.            MyBase.New(options)
18.        End Sub
20.        Public Overridable Property ContactType() As DbSet(Of ContactType)
21.        Public Overridable Property Contacts() As DbSet(Of Contacts)
23.        Protected Overrides Sub OnConfiguring(optionsBuilder As DbContextOptionsBuilder)
24.            If Not optionsBuilder.IsConfigured Then
25.                Dim configurationHelper = New ConfigurationHelper
26.                _connectionString = configurationHelper.ConnectionString
28.                If Not optionsBuilder.IsConfigured Then
29.                    optionsBuilder.UseSqlServer(_connectionString)
30.                End If
32.            End If
33.        End Sub
35.        Protected Overrides Sub OnModelCreating(modelBuilder As ModelBuilder)
37.            modelBuilder.ApplyConfiguration(New ContactTypeConfiguration())
38.            modelBuilder.ApplyConfiguration(New ContactsConfiguration())
40.            OnModelCreatingPartial(modelBuilder)
42.        End Sub
44.        Partial Private Sub OnModelCreatingPartial(modelBuilder As ModelBuilder)
45.        End Sub
46.    End Class
47.End Namespace

Entity Framework Core self-contained connection

General practice is to use appsettings.json

  "database": {
    "DatabaseServer": ".\\SQLEXPRESS",
    "Catalog": "NorthWind2020",
    "IntegratedSecurity": "true",
    "UsingLogging": "true"

Then to read the connection string from appsettings.json in the DbContext.

Create a private method

Private Shared Function BuildConnection() As String
    Dim configuration = (New ConfigurationBuilder()).AddJsonFile("appsettings.json", True, True).Build()
    Dim sections = configuration.GetSection("database").GetChildren().ToList()
    Return $"Data Source={sections(1).Value};Initial Catalog={sections(0).Value};Integrated Security={sections(2).Value}"
End Function

Which is called in OnConfiguring method.

Protected Overrides Sub OnConfiguring(optionsBuilder As DbContextOptionsBuilder)
    If Not optionsBuilder.IsConfigured Then
    End If
End Sub

Going a step farther consider creating methods which BuildConnection is used along with setting up for logging and or events and interceptors as per below.

Private Sub NormalConfiguration(optionsBuilder As DbContextOptionsBuilder)
End Sub
Private Sub NormalConfigurationEnableDetailedErrors(optionsBuilder As DbContextOptionsBuilder)
        LogTo(AddressOf Console.WriteLine).EnableDetailedErrors()
End Sub
Private Sub WithSaveChangesInterceptor(optionsBuilder As DbContextOptionsBuilder)
        AddInterceptors(New SavedChangesInterceptor).
End Sub
Private Sub WithCommandInterceptor(optionsBuilder As DbContextOptionsBuilder)
        AddInterceptors(New CommandInterceptor).
End Sub
Private Shared Sub LogQueryInfoToDebugOutputWindow(ByVal optionsBuilder As DbContextOptionsBuilder)
        EnableSensitiveDataLogging().LogTo(Sub(message) Debug.WriteLine(message))
End Sub

Then for multiple environments expand appsettings as per below.  Environment could be an  Enum where each member is numbered for dev, staging, prod environments instead of a Boolean.

  "ConnectionStrings": {
    "DevelopmentConnection": "Server=.\\SQLEXPRESS;Database=NorthWind2020;Integrated Security=true",
    "ProductionConnection": "Server=ProdServerDoesNotExists;Database=NorthWind2020Prod;Integrated Security=true"
  "Environment": {
    "Production": false

Custom configurations using appsettings.json

The appsettings.json file is a convenient way to store and retrieve your application’s configuration.  For VB coders working with desktop solutions, there are no code samples other than ASP.NET Core hence this section will provide the core code to use appsettings.json (and note a different name can be used while sticking with appsettings.json is the standard).

NuGet packages

In Visual Studio, double click on a .NET Core project and and the following, save/close the file.
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />

Version numbers may change and if so under manage NuGet packages an alert will appear if there are newer versions which allows updating to a current version.

Next, add a appsetings.json file and set copy to output folder to copy if newer under properties for the file.
  "Environment": {
    "ConnectionString": "Data Source=DevServer;Initial Catalog=NorthWindAzure;Integrated Security=True",
    "MailTo": ";;",
    "UseGeoLocation": true

Add the following class
  • The constructor makes a call to Setup which in turn invokes GetConfiguration for telling .NET where to find the configuration file
  • Lines 46,47,48 retrieve setting and cast as needed to the proper type defined by the read-only properties in ApplicationConfiguration.

01.Imports Microsoft.Extensions.Configuration
03.Public NotInheritable Class ApplicationConfiguration
04.    Private Shared ReadOnly Lazy As New _
05.        Lazy(Of ApplicationConfiguration)(Function() New ApplicationConfiguration())
07.    ''' <summary>
08.    ''' Access point to methods and properties
09.    ''' </summary>
10.    Public Shared ReadOnly Property Instance() As ApplicationConfiguration
11.        Get
12.            Return Lazy.Value
13.        End Get
14.    End Property
16.    Private Property Settings() As IConfiguration
18.    Public Property MailToAddressList() As List(Of String)
20.    Private Sub New()
21.        SetUp()
22.    End Sub
23.    ''' <summary>
24.    ''' Initialize configuration to read json file
25.    ''' </summary>
26.    ''' <returns></returns>
27.    Private Function GetConfiguration() As IConfiguration
29.        Dim builder = (New ConfigurationBuilder()).
30.                SetBasePath(AppContext.BaseDirectory).
31.                AddJsonFile("appsettings.json",
32.                            [optional]:=True,
33.                            reloadOnChange:=True)
35.        Return builder.Build()
37.    End Function
38.    ''' <summary>
39.    ''' Get values from json file, assign to properties
40.    ''' </summary>
41.    Private Sub SetUp()
43.        MailToAddressList = New List(Of String)
44.        Settings = GetConfiguration()
46.        _connectionString = Settings("Environment:ConnectionString")
47.        _mailAddress = Settings("Environment:MailTo").Split(";"c).ToList()
48.        _useGeoLocation = CType(Settings("Environment:UseGeoLocation"), Boolean)
50.    End Sub
52.    Private Shared _mailAddress As List(Of String)
53.    ''' <summary>
54.    ''' Mail addresses for sending error report
55.    ''' </summary>
56.    ''' <returns></returns>
57.    Public ReadOnly Property MailAddresses() As List(Of String)
58.        Get
59.            Return _mailAddress
60.        End Get
61.    End Property
62.    Private Shared _connectionString As String
63.    ''' <summary>
64.    ''' Database connection string
65.    ''' </summary>
66.    ''' <returns></returns>
67.    Public ReadOnly Property ConnectionString() As String
68.        Get
69.            Return _connectionString
70.        End Get
71.    End Property
73.    Private Shared _useGeoLocation As Boolean
74.    ''' <summary>
75.    ''' Get current location
76.    ''' </summary>
77.    ''' <returns>True collect, False do not collect geo location</returns>
78.    Public ReadOnly Property UseGeoLocation() As Boolean
79.        Get
80.            Return _useGeoLocation
81.        End Get
82.    End Property
83.End Class

Reading the ConnectionString

Read mail addresses

Read UseGeoLocation
Dim geoLocation As Boolean = ApplicationConfiguration.Instance.UseGeoLocation

In the above samples, all code is within the same project. If there will be many projects that used the same settings consider using a class project to read settings as presented in the following class project.

Complex settings

With reboust applications many times there will be a need to have multiple environments e.g. development, test and production. The following appsettings file is one fictitious example.

  "Environment": {
    "Name": "Development"
  "GeneralSettings": [
      "Environment": "Development",
      "ReloadApplicationOnEveryRequest": true,
      "Trace": false,
      "Reload": "reload",
      "Password": true,
      "ConnectionString": "Data Source=DevServer;Initial Catalog=NorthWindAzure;Integrated Security=True",
      "DiConfiguration": {
        "Dsn": "ABC",
        "Globals": "globals",
        "Globals2": "globals2",
        "MailTo": ";;",
        "ExitLink": "/ocs4/",
        "OcsLink": null,
        "MfLink": "",
        "MfUser": null,
        "MfPass": "",
        "UseGeoLocation": true,
        "ResetPinLocation": "/pinchange/begin/",
        "BaseServerAddress": "xxx4",
        "UirTakeTest": false,
        "QryCacheShort": "00:00:10",
        "QryCacheLong": "00:00:05"
      "Environment": "Test",
      "ReloadApplicationOnEveryRequest": false,
      "Trace": false,
      "Reload": "reload",
      "Password": true,
      "ConnectionString": "Data Source=TestServer;Initial Catalog=NorthWindAzure;Integrated Security=True",
      "DiConfiguration": {
        "Dsn": "DEF",
        "Globals": "globals",
        "Globals2": "globals2",
        "MailTo": ";;",
        "ExitLink": "/ocs4/",
        "OcsLink": null,
        "MfLink": "",
        "MfUser": null,
        "MfPass": "",
        "UseGeoLocation": true,
        "ResetPinLocation": "/pinchange/begin/",
        "BaseServerAddress": "xxx4",
        "UirTakeTest": false,
        "QryCacheShort": "00:10:00",
        "QryCacheLong": "00:01:00"
      "Environment": "Production",
      "ReloadApplicationOnEveryRequest": false,
      "Trace": false,
      "Reload": "reload",
      "Password": true,
      "ConnectionString": "Data Source=ProductionServer;Initial Catalog=NorthWindAzure;Integrated Security=True",
      "DiConfiguration": {
        "Dsn": "GHI",
        "Globals": "globals",
        "Globals2": "globals2",
        "MailTo": ";;",
        "ExitLink": "/ocs4/",
        "OcsLink": null,
        "MfLink": "",
        "MfUser": null,
        "MfPass": "",
        "UseGeoLocation": true,
        "ResetPinLocation": "/pinchange/begin/",
        "BaseServerAddress": "xxx4",
        "UirTakeTest": false,
        "QryCacheShort": "06:00:00",
        "QryCacheLong": "00:30:00",
        "ConnectionString": "Prod connection"

To create this, see the following project and read the file for instructions. Now create a new .NET Console or Windows Form project, add a reference to this project which contains classes and methods to read settings. This is followed by adding appsettings.json, add the Json above, set copy to output folder to copy if newer under properties for the file.

The following shows reading settings, note that there are custom console method helpers included in ConsoleHelper project.
Imports Classes
Imports ConsoleHelpers
Module Program
    Sub Main(args As String())
        WriteHeader("Configuration code sample")
        Console.WriteLine($"Environment (Singleton): {ApplicationSettings.Instance.Environment}")
        Console.WriteLine($"            Environment: {Helper.Environment}")
        Console.WriteLine($"                    Dsn: {ApplicationSettings.Instance.Dsn}")
        Console.WriteLine($"      Connection string: {ApplicationSettings.Instance.ConnectionString}")
        Dim mailAddress = ApplicationSettings.Instance.MailAddresses
        Console.WriteLine("Mail addresses")
        For Each address In mailAddress
        Console.WriteLine($"QryCacheShort: {ApplicationSettings.Instance.QryCacheShort}")
    End Sub
End Module

Included projects

Rather than step through each project here take time to examine all the projects as each one has something different to offer. Start with Basic2 followed by Basic1/ConfigurationHelper together.


Two distinct ways to read settings from files have been presented with the focus on moving to appsettings.json over app.config when creating .NET Core desktop solutions with plenty of sample code to get started.

See also

Entity Framework Core 3.x database connection
.NET Core desktop application configurations (C#)

Source code

Use Visual Studio or Git-Desktop to clone the following GitHub repository.