Creating the WebAPI–part 13

I am now tired of continuously improving the console application – so now some work that others can see really.  Creating the WebAPI is simple as a project  – and I was amazed to see a WeatherForecast controller.

I need just to be able to see the today exchange rates via API . So created a TodayRates , modify the launchSettings.json in order to start with my controller.

I need the plugin that loads to be a global dependency. So I add as a Singletion in the services

services.AddSingleton< LoadExchangeProviders>(new LoadExchangeProviders(“plugins”));

and then I inject into the controller constructor ( I can do in the method also, but many methods needs the same dependency )

public TodayRates(ILogger<TodayRates> logger, LoadExchangeProviders prov)
{
_logger = logger;
_prov = prov;
}

 

Now I need a method to see what are the banks / plugins that are loaded . Linq to the rescue :

 

[HttpGet]
public IEnumerable<string> Banks()
{
return _prov
.LoadExchange()
.Select(it=>it.Bank)
.ToArray();
}

Now we should load the data from the provider to show actual rates

public async IAsyncEnumerable<ExchangeRates> Rates(string bank)
{
var provBank = _prov
.LoadExchange()
.FirstOrDefault(it => string.Equals(bank, it.Bank, StringComparison.InvariantCultureIgnoreCase));

switch (provBank)
{
case null:
yield return null;
break;
default:
{
await foreach (var data in provBank.GetActualRates())
{
yield return data;
}

break;
}
}

}

 

All good. There are  3 problems:

  1. How to put the plugins for the console and web api ?
  2. How to cache the data  ? ( plugins / exchange rates)
  3. Should we throw an exception when a bank does not exists, instead of returning null ?

 

Thinking of this code, I realized that I begin to put logic into controllers. So – let’s move from the controller to the business.

For example, now I have this:

[HttpGet]
public IEnumerable<string> Banks()
{
return _prov.Banks();
}

 

And this

[HttpGet]
public IAsyncEnumerable<ExchangeRates> Rates(string bank)
{
return _prov.Rates(bank);
}

So now I can change in the Business Layer without problems.

Looking at the Console Application vs  WebAPI, I realized that are different. The console is loading the whole data from the providers – the WebAPI is loading on demand.  We could do for the console the same behavior  – but the console is loading very fast all data.

For the answer at

Should we throw an exception when a bank does not exists, instead of returning null ?

– seems to be yes.

So instead of

case null:
yield return null;
I put

case null:
throw new ArgumentOutOfRangeException(nameof(bank),$”cannot find {bank}”);

 

For the 2 questions, the answer next time.

 

Infovalutar

And one hour passes...
(This is the result of 1 hour per day auto-challenge as a full cycle developer for an exchange rates application)
( You can see the sources at https://github.com/ignatandrei/InfoValutar/ )
NrPost 
1Start
2Reading NBR from internet
3Source control and build
4Badge and test
5CI and action
6Artifacts and dotnet try
7Docker with .NET Try
8ECB
9Intermezzo - Various implementations for programmers
10Intermezzo - similar code - options
11Plugin implementation
12GUI for console
13WebAPI
14Plugin in .NET Core 3
15Build and Versioning
16Add swagger
17Docker - first part
18Docker - second part
19Docker - build Azure
20Pipeline send to Docker Hub
21Play with Docker - online
22Run VSCode and Docker
23Deploy Azure
24VSCode see tests and powershell
25Code Coverage
26Database in Azure
27Sql In Memory or Azure
28Azure ConString, RSS
29Middleware for backward compatibility
30Identical Tables in EFCore
31Multiple Data in EFCore
32Dot net try again
33Start Azure Function
34Azure function - deploy
35Solving my problems
36IAsyncEnumerable transformed to IEnumerable and making Azure Functions works
37Azure functions - final
38Review of 37 hours
39Last Commit in AzureDevOps
40Create Angular WebSite
41Add static Angular to WebAPI .NET Core
42Docker for Angular
43Angular and CORS
44SSL , VSCode, Docker
45Routing in Angular
46RxJS for Routing
47RxJs Unsubscribe