108
CHAPTER 5 | Designing and Developing Multi-Container and Microservice-Based .NET Applications
.
Take
(pageSize)
.
ToListAsync
();
itemsOnPage =
ChangeUriPlaceholder
(itemsOnPage);
var
model =
new
PaginatedItemsViewModel
(
pageIndex, pageSize, totalItems, itemsOnPage);
return
Ok
(model);
}
//...
}
Saving data
Data is created, deleted, and modified in the database using instances of your entity classes. You
could add code like the following hard-coded example (mock data, in this case) to your Web API
controllers.
var
catalogItem =
new
CatalogItem
() {CatalogTypeId=
2
, CatalogBrandId=
2
,
Name=
"Roslyn T-Shirt"
, Price =
12
};
_context.
Catalog
.
Add
(catalogItem);
_context.
SaveChanges
();
Dependency Injection in ASP.NET Core and Web API controllers
In ASP.NET Core, you can use Dependency Injection (DI) out of the box. You do not need to set up a
third-party Inversion of Control (IoC) container, although you can plug your preferred IoC container
into the ASP.NET Core infrastructure if you want. In this case, it means that you can directly inject the
required EF DBContext or additional repositories through the controller constructor.
In the
CatalogController
class mentioned earlier,
CatalogContext
(which inherits from
DbContext
)
type is injected along with the other required objects in the
CatalogController()
constructor.
An important configuration to set up in the Web API project is the DbContext class registration into
the service’s IoC container. You typically do so in the
Program.cs
file by calling the
builder.Services.AddDbContext()
method, as shown in the following
simplified
example:
// Additional code...
builder.
Services
.
AddDbContext
(options =>
{
options.
UseSqlServer
(builder.
Configuration
[
"ConnectionString"
],
sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.
MigrationsAssembly
(
typeof
(Program).
GetTypeInfo
().
Assembly
.
GetName
().
Name
);
//Configuring Connection Resiliency:
sqlOptions.
EnableRetryOnFailure
(maxRetryCount:
5
,
maxRetryDelay: TimeSpan.
FromSeconds
(
30
),
errorNumbersToAdd:
null
);
});
109
CHAPTER 5 | Designing and Developing Multi-Container and Microservice-Based .NET Applications
// Changing default behavior when client evaluation occurs to throw.
// Default in EFCore would be to log warning when client evaluation is done.
options.
ConfigureWarnings
(warnings => warnings.
Throw
(
RelationalEventId.
QueryClientEvaluationWarning
));
});
Additional resources
•
Querying Data
https://learn.microsoft.com/ef/core/querying/index
•
Saving Data
https://learn.microsoft.com/ef/core/saving/index
The DB connection string and environment variables used by Docker
containers
You can use the ASP.NET Core settings and add a ConnectionString property to your settings.json file
as shown in the following example:
{
"ConnectionString"
:
"Server=tcp:127.0.0.1,5433;Initial
Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=[PLACEHOLDER]"
,
"ExternalCatalogBaseUrl"
:
"http://host.docker.internal:5101"
,
"Logging"
:
{
"IncludeScopes"
:
false
,
"LogLevel"
:
{
"Default"
:
"Debug"
,
"System"
:
"Information"
,
"Microsoft"
:
"Information"
}
}
}
The settings.json file can have default values for the ConnectionString property or for any other
property. However, those properties will be overridden by the values of environment variables that
you specify in the docker-compose.override.yml file, when using Docker.
From your docker-compose.yml or docker-compose.override.yml files, you can initialize those
environment variables so that Docker will set them up as OS environment variables for you, as shown
in the following docker-compose.override.yml file (the connection string and
other lines wrap in this
example, but it would not wrap in your own file).
# docker-compose.override.yml
#
catalog-api:
environment:
-
ConnectionString=Server=sqldata;Database=Microsoft.eShopOnContainers.Services.CatalogDb;Use
r Id=sa;Password=
[
PLACEHOLDER
]
# Additional environment variables for this service
ports:
-
"5101:80"
110
CHAPTER 5 | Designing and Developing Multi-Container and Microservice-Based .NET Applications
The docker-compose.yml files at the solution level are not only more flexible than configuration files
at the project or microservice level, but also more secure if you override the environment variables
declared at the docker-compose files with values set from your deployment tools, like from Azure
DevOps Services Docker deployment tasks.
Finally, you can get that value from your code by using
builder.Configuration\["ConnectionString"\]
, as shown in an earlier code example.
However,
for production environments, you might want to explore additional ways on how to store
secrets like the connection strings. An excellent way to manage application secrets is using
Azure Key
Vault
.
Azure Key Vault helps to store and safeguard cryptographic keys and secrets used by your cloud
applications and services. A secret is anything you want to keep strict control of, like API keys,
connection strings, passwords, etc. and strict
control includes usage logging, setting expiration,
managing access,
among others
.
Azure Key Vault allows a detailed control level of the application secrets usage without the need to let
anyone know them. The secrets can even be rotated for enhanced security without disrupting
development or operations.
Applications have to be registered in the organization’s Active Directory, so they can use the Key
Vault.
You can
check the
Key Vault Concepts documentation
for more details.
Dostları ilə paylaş: