Edition 0 Updated to asp. Net core 0



Yüklə 11,82 Mb.
Pdf görüntüsü
səhifə98/288
tarix12.07.2023
ölçüsü11,82 Mb.
#136458
1   ...   94   95   96   97   98   99   100   101   ...   288
public
class
CatalogItem 

public
int
Id { 
get

set
; } 
public
string
Name { 
get

set
; } 
public
string
Description { 
get

set
; } 
public
decimal
Price { 
get

set
; } 
public
string
PictureFileName { 
get

set
; } 
public
string
PictureUri { 
get

set
; } 
public
int
CatalogTypeId { 
get

set
; } 
public
CatalogType CatalogType { 
get

set
; } 
public
int
CatalogBrandId { 
get

set
; } 
public
CatalogBrand CatalogBrand { 
get

set
; } 
public
int
AvailableStock { 
get

set
; } 
public
int
RestockThreshold { 
get

set
; } 
public
int
MaxStockThreshold { 
get

set
; } 
public
bool
OnReorder { 
get

set
; } 
public
CatalogItem
() { } 
// Additional code ...

You also need a DbContext that represents a session with the database. For the catalog microservice, 
the CatalogContext class derives from the DbContext base class, as shown in the following example: 
public
class
CatalogContext : DbContext 

public
CatalogContext
(DbContextOptions options) : 
base
(options) 
{ } 
public
DbSet CatalogItems { 
get

set
; } 
public
DbSet CatalogBrands { 
get

set
; } 
public
DbSet CatalogTypes { 
get

set
; } 
// Additional code ...

You can have additional 
DbContext
implementations. For example, in the sample Catalog.API 
microservic
e, there’s a second 
DbContext
named 
CatalogContextSeed
where it automatically 
populates the sample data the first time it tries to access the database. This method is useful for demo 
data and for automated testing scenarios, as well. 


107 
CHAPTER 5 | Designing and Developing Multi-Container and Microservice-Based .NET Applications 
Within the 
DbContext
, you use the 
OnModelCreating
method to customize object/database entity 
mappings and other 
EF extensibility points

Querying data from Web API controllers 
Instances of your entity classes are typically retrieved from the database using Language-Integrated 
Query (LINQ), as shown in the following example: 
[
Route
(
"api/v1/[controller]"
)] 
public
class
CatalogController : ControllerBase 

private
readonly
CatalogContext _catalogContext; 
private
readonly
CatalogSettings _settings; 
private
readonly
ICatalogIntegrationEventService _catalogIntegrationEventService; 
public
CatalogController

CatalogContext context, 
IOptionsSnapshot settings, 
ICatalogIntegrationEventService catalogIntegrationEventService) 

_catalogContext = context ?? 
throw
new
ArgumentNullException
(
nameof
(context)); 
_catalogIntegrationEventService = catalogIntegrationEventService 
?? 
throw
new
ArgumentNullException
(
nameof
(catalogIntegrationEventService)); 
_settings = settings.
Value

context.
ChangeTracker
.
QueryTrackingBehavior
= QueryTrackingBehavior.
NoTracking


// GET api/v1/[controller]/items[?pageSize=3&pageIndex=10]
[HttpGet] 
[
Route
(
"items"
)] 
[
ProducesResponseType
(
typeof
(PaginatedItemsViewModel), 
(
int
)HttpStatusCode.
OK
)] 
[
ProducesResponseType
(
typeof
(IEnumerable), (
int
)HttpStatusCode.
OK
)] 
[
ProducesResponseType
((
int
)HttpStatusCode.
BadRequest
)] 
public
async Task 
ItemsAsync

[FromQuery]
int
pageSize = 
10

[FromQuery]
int
pageIndex = 
0

string
ids = 
null


if
(!
string
.
IsNullOrEmpty
(ids)) 

var
items = await 
GetItemsByIdsAsync
(ids); 
if
(!items.
Any
()) 

return
BadRequest
(
"ids value invalid. Must be comma-separated list of 
numbers"
); 

return
Ok
(items); 

var
totalItems = await _catalogContext.
CatalogItems
.
LongCountAsync
(); 
var
itemsOnPage = await _catalogContext.
CatalogItems
.
OrderBy
(c => c.
Name

.
Skip
(pageSize * pageIndex) 


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. 

Yüklə 11,82 Mb.

Dostları ilə paylaş:
1   ...   94   95   96   97   98   99   100   101   ...   288




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©azkurs.org 2024
rəhbərliyinə müraciət

gir | qeydiyyatdan keç
    Ana səhifə


yükləyin