Windows service for working with exchange rates of the National Bank of Ukraine written in .NET Core 8.0 | C# 12
sc create "NBU Rates Service" binpath="path/to/NBURatesService.exe"
sc delete "NBU Rates Service"
sc config "NBU Rates Service" start= auto
The configuration file config.js
is located in the folder the executable file NBURatesService.exe
and looks like this:
{
//In milliseconds
"FetchFrequency": 5000,
//The output will be in the folder with the executable file if the field is empty
"OutputPath": "",
//The output file name will be Rates if the field is empty
"OutputFileName": "",
//The output file type name will be json if the field is empty
// (You can use this types: xml, json, csv)
"FileType": ""
}
The program configuration is reloaded before each data fetch, so after changing the configuration file, all settings are automatically applied without restarting the service.
Thanks to this, the file can be overwritten in other programs and dynamically change saving settings.
Windows
.NET Core 8.0
-
They are used to correctly start the service on a Windows system.
Microsoft.Extensions.Hosting
Microsoft.Extensions.Hosting.WindowsServices
-
Json serialization and deserialization for API Models:
Newtonsoft.Json
This project does NOT use control codes to control the service, since this is outdated (ServiceBase.OnCustomCommand(Int32)
) and is not an appropriate method of application communication.
In place, the configuration is updated itself before loading data from the API without using codes. (Since the information in the API is rarely updated, auto-updating the config does not require many resources)
PS: using WindowsServiceLifetime is a bad practice due to the fact that the source code of this class is poorly written. ServiceBase is only suitable for .NET Framework, which is an outdated technology so my choise is BackgraoundService
Use Event Viewer
(Windows App)!
There you can also see all the service
logs. I recommend adding
"Custom View" to view logs only for this service
- Error! Can not get data from https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json
- Solution: Check your internet connection
- Config error
- Solution: Replace your config.json to new one (see #Configuration)
A configuration class for the NBU Currency Rates Service. The Config
class is responsible for initializing and managing configuration settings used by the service, including fetching frequencies, output file types, file names, and paths.
NBUCurrencyRatesService.Configuration
The Config
class handles the setup and management of configuration settings for the NBU Currency Rates Service. It reads configurations from a JSON file and provides mechanisms for reloading configurations dynamically.
public Config(IConfiguration configuration, ILogger logger)
- Parameters:
configuration
: An instance ofIConfiguration
to access configuration settings.logger
: An instance ofILogger
to log information.
private readonly ILogger _logger;
private IConfiguration _configuration;
public int FetchFrequency;
public OutputType FileType;
public string OutputFileName;
public string OutputPath;
Constructor that initializes the Config
class with the provided configuration
and logger
. It calls the Initialize
method to load configuration settings.
Reloads the configuration settings by reinitializing with the default configuration. Logs the reload action.
Builds and returns the default configuration from the config.json
file located at the application's base directory.
Initializes the configuration settings from the provided configuration
object. It sets the FetchFrequency
, OutputPath
, OutputFileName
, and FileType
fields.
- FetchFrequency: The frequency (in ms) at which the service fetches currency rates.
- FileType: The type of output file (JSON, CSV, XML).
- OutputFileName: The name of the output file.
- OutputPath: The path where the output file will be saved.
{
"FetchFrequency": "15000",
"OutputFileName": "CurrencyRates",
"OutputPath": "D:/Rates",
"FileType": "JSON"
}
- Create an instance of the
Config
class by passing anIConfiguration
object and anILogger
object. - Use the
Reload
method to reload the configuration settings if needed.
var configuration = Config.GetDefaultConfiguration();
var logger = LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger<Config>();
var config = new Config(configuration, logger);
Console.WriteLine($"Fetch Frequency: {config.FetchFrequency}");
Console.WriteLine($"Output File Type: {config.FileType}");
Console.WriteLine($"Output File Name: {config.OutputFileName}");
Console.WriteLine($"Output Path: {config.OutputPath}");
- Ensure that the
config.json
file is present in the base directory of the application. - The
FileType
field is parsed as an enumeration, ensure the value in the configuration file matches one of theOutputType
enumeration values. - Logging is enabled to track configuration reloads and other operations.
A service class for fetching currency rates from the National Bank of Ukraine (NBU) API. The NBUGrabber
class is responsible for making HTTP requests to the NBU API and deserializing the response into a list of currency rate objects.
NBUCurrencyRatesService.API
The NBUGrabber
class handles the fetching of currency rates from the NBU API. It sends HTTP requests to the specified API endpoint, retrieves the data in JSON format, and deserializes it into a list of CurrencyRate
objects.
public NBUGrabber(ILogger logger)
- Parameter:
logger
: An instance ofILogger
to log information and errors.
private const string ApiUrl = "https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json";
Fetches the currency rates from the NBU API.
- Returns:
- A
Task
that represents the asynchronous operation. The task result contains a list ofCurrencyRate
objects ornull
if an error occurs.
- A
- Newtonsoft.Json: Used for deserializing the JSON response from the API.
- Create an instance of the
NBUGrabber
class by passing anILogger
object. - Call the
FetchRates
method to fetch currency rates from the NBU API.
var logger = LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger<NBUGrabber>();
var grabber = new NBUGrabber(logger);
var rates = await grabber.FetchRates();
if (rates != null)
{
foreach (var rate in rates)
{
Console.WriteLine($"Currency: {rate.CurrencyCode}, Rate: {rate.Rate}");
}
}
else
{
Console.WriteLine("Failed to fetch currency rates.");
}
- Logs an informational message when fetching data from the API.
- Logs an error message if an exception occurs during the fetch operation.
- Ensure that the
CurrencyRate
class is defined to match the structure of the JSON response from the NBU API. - The
FetchRates
method usesHttpClient
to send HTTP requests. Make sure to handle the proper disposal ofHttpClient
if used in a different context.
public class CurrencyRate
{
// ReSharper disable StringLiteralTypo
[JsonProperty("r030")] public int R030 { get; set; }
[JsonProperty("txt")] public string? FullName { get; set; }
[JsonProperty("cc")] public string? CurrencyCode { get; set; }
[JsonProperty("rate")] public float Rate { get; set; }
[JsonProperty("exchangedate")] public string? ExchangeDate { get; set; }
// ReSharper restore StringLiteralTypo
}
- The NBU API URL used to fetch currency rates is
https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json
.
A service class for saving currency rates to various file formats. The RatesWriter
class provides methods to save currency rates as JSON, CSV, or XML files based on the specified output type.
NBUCurrencyRatesService.API
The RatesWriter
class is responsible for saving currency rates to files in different formats. It accepts a collection of currency rates, a file path, a file name, and the desired output type (JSON, CSV, or XML). Based on the output type, it writes the rates to the corresponding file format.
public RatesWriter(ILogger logger)
- Parameter:
logger
: An instance ofILogger
to log information and errors.
public void Save(IEnumerable<CurrencyRate> rates, string path, string fileName, OutputType fileType)
Saves the currency rates to a file based on the specified output type.
- Parameters:
rates
: A collection of currency rates to be saved.path
: The directory path where the file will be saved.fileName
: The name of the file to be saved.fileType
: The output file type (JSON, CSV, or XML).
- Newtonsoft.Json: Used for serializing/deserializing JSON data.
- System.Xml.Serialization: Used for serializing/deserializing XML data.
- Create an instance of the
RatesWriter
class by passing anILogger
object. - Call the
Save
method with the currency rates, file path, file name, and output type to save the rates to the desired file format.
var logger = LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger<RatesWriter>();
var writer = new RatesWriter(logger);
var rates = GetCurrencyRates(); // Some magic to get Currency Rates (NBUGrabber for exampele)
var path = "/path/to/save";
var fileName = "CurrencyRates";
writer.Save(rates, path, fileName, OutputType.Json);
- Logs an error if the provided path or file name is empty.
- Logs an informational message after successfully saving the rates to a file.
- The
Save
method uses switch-case statements to determine the output file type and calls the corresponding private method (SaveJson
,SaveCsv
, orSaveXml
) accordingly.
- JSON: Currency rates are saved as JSON objects in a
.json
file. - CSV: Currency rates are saved as comma-separated values in a
.csv
file. - XML: Currency rates are saved as XML elements in an
.xml
file.
[
{
"r030": 36,
"txt": "Австралійський долар",
"cc": "AUD",
"rate": 26.9573,
"exchangedate": "03.06.2024"
},
{
"r030": 124,
"txt": "Канадський долар",
"cc": "CAD",
"rate": 29.7151,
"exchangedate": "03.06.2024"
}
]
R030,FullName,CurrencyCode,Rate,ExchangeDate
36,Австралійський долар,AUD,26.9573,03.06.2024
124,Канадський долар,CAD,29.7151,03.06.2024
156,Юань Женьміньбі,CNY,5.5984,03.06.2024
203,Чеська крона,CZK,1.7796,03.06.2024
208,Данська крона,DKK,5.8972,03.06.2024
344,Гонконгівський долар,HKD,5.1853,03.06.2024
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfCurrencyRate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CurrencyRate>
<R030>36</R030>
<FullName>Австралійський долар</FullName>
<CurrencyCode>AUD</CurrencyCode>
<Rate>26.9573</Rate>
<ExchangeDate>03.06.2024</ExchangeDate>
</CurrencyRate>
<CurrencyRate>
<R030>124</R030>
<FullName>Канадський долар</FullName>
<CurrencyCode>CAD</CurrencyCode>
<Rate>29.7151</Rate>
<ExchangeDate>03.06.2024</ExchangeDate>
</CurrencyRate>
</ArrayOfCurrencyRate>