Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge main into live #42569

Merged
merged 5 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 51 additions & 42 deletions docs/architecture/maui/authentication-and-authorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Authentication and Authorization
description: Providing security and identity management for .NET MAUI application
author: michaelstonis
no-loc: [MAUI]
ms.date: 05/30/2024
ms.date: 09/10/2024
---

# Authentication and authorization
Expand Down Expand Up @@ -46,7 +46,7 @@ The eShop multi-platform app communicates with the identity microservice, which
### Adding IdentityServer to a web application

In order for an ASP.NET Core web application to use IdentityServer, it must be added to the web application's Visual Studio solution. For more information, see [Setup and Overview](https://docs.duendesoftware.com/identityserver/v7/quickstarts/) in the IdentityServer documentation.
Once IdentityServer is included in the web application's Visual Studio solution, it must be added to its HTTP request processing pipeline to serve requests to OpenID Connect and OAuth 2.0 endpoints. This is configured in the `Identity.API` project's `Program.cs`, as demonstrated in the following code example:
Once IdentityServer is included in the web application's Visual Studio solution, it must be added to its HTTP request processing pipeline to serve requests to OpenID Connect and OAuth 2.0 endpoints. This is configured in the `Identity.API` project's _Program.cs_, as demonstrated in the following code example:

```csharp

Expand All @@ -59,23 +59,28 @@ Order matters in the web application's HTTP request processing pipeline. Therefo

### Configuring IdentityServer

IdentityServer should be configured in the ConfigureServices method in the web application's Startup class by calling the `services.AddIdentityServer` method, as demonstrated in the following code example from the eShop reference application:
IdentityServer is configured in the `Identity.API` project's _Program.cs_ by calling the `AddIdentityServer` method, as demonstrated in the following code example from the eShop reference application:

```csharp
public void ConfigureServices(IServiceCollection services)
{
    services
.AddIdentityServer(x => x.IssuerUri = "null")
        .AddSigningCredential(Certificate.Get())
        .AddAspNetIdentity<ApplicationUser>()
        .AddConfigurationStore(builder =>
            builder.UseSqlServer(connectionString, options =>
                options.MigrationsAssembly(migrationsAssembly)))
        .AddOperationalStore(builder =>
            builder.UseSqlServer(connectionString, options =>
                options.MigrationsAssembly(migrationsAssembly)))
        .Services.AddTransient<IProfileService, ProfileService>();
}
builder.Services.AddIdentityServer(options =>
{
options.Authentication.CookieLifetime = TimeSpan.FromHours(2);

options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;

// TODO: Remove this line in production.
options.KeyManagement.Enabled = false;
})
.AddInMemoryIdentityResources(Config.GetResources())
.AddInMemoryApiScopes(Config.GetApiScopes())
.AddInMemoryApiResources(Config.GetApis())
.AddInMemoryClients(Config.GetClients(builder.Configuration))
.AddAspNetIdentity<ApplicationUser>()
// TODO: Not recommended for production - you need to store your key material somewhere secure
.AddDeveloperSigningCredential();
```

After calling the `services.AddIdentityServer` method, additional fluent APIs are called to configure the following:
Expand Down Expand Up @@ -147,33 +152,37 @@ public static IEnumerable<Client> GetClients(Dictionary<string,string> clien
    return new List<Client>
    {
        // Omitted for brevity
        new Client
        {
            ClientId = "maui",
            ClientName = "eShop .NET MAUI OpenId Client",
            AllowedGrantTypes = GrantTypes.Hybrid,
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            RedirectUris = { clientsUrl["maui"] },
            RequireConsent = false,
            RequirePkce = true,
            PostLogoutRedirectUris = { $"{clientsUrl["maui"]}/Account/Redirecting" },
            AllowedCorsOrigins = { "http://eshopmaui" },
            AllowedScopes = new List<string>
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.OfflineAccess,
                "orders",
                "basket"
            },
            AllowOfflineAccess = true,
            AllowAccessTokensViaBrowser = true,
new Client
{
ClientId = "maui",
ClientName = "eShop MAUI OpenId Client",
AllowedGrantTypes = GrantTypes.Code,
//Used to retrieve the access token on the back channel.
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { configuration["MauiCallback"] },
RequireConsent = false,
RequirePkce = true,
PostLogoutRedirectUris = { $"{configuration["MauiCallback"]}/Account/Redirecting" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.OfflineAccess,
"orders",
"basket",
"mobileshoppingagg",
"webhooks"
},
//Allow requesting refresh tokens for long lived API access
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true,
AlwaysIncludeUserClaimsInIdToken = true,
AccessTokenLifetime = 60 * 60 * 2, // 2 hours
IdentityTokenLifetime = 60 * 60 * 2 // 2 hours
        }
}
    };
}
```
Expand Down
4 changes: 2 additions & 2 deletions docs/architecture/maui/mvvm.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Model-View-ViewModel
description: Overview of the Model-View-ViewModel pattern used by .NET MAUI
author: michaelstonis
no-loc: [MAUI]
ms.date: 05/30/2024
ms.date: 09/10/2024
---

# Model-View-ViewModel (MVVM)
Expand Down Expand Up @@ -339,7 +339,7 @@ The advantage of using the `EventToCommandBehavior` to execute a command when an

## Invoking behaviors from a view

The EventToCommandBehavior is particularly useful for attaching a command to a control that doesn't support commands. For example, the LoginView uses the `EventToCommandBehavior` to execute the `ValidateCommand` when the user changes the value of their password, as shown in the following code:
The `EventToCommandBehavior` is particularly useful for attaching a command to a control that doesn't support commands. For example, the LoginView uses the `EventToCommandBehavior` to execute the `ValidateCommand` when the user changes the value of their password, as shown in the following code:

```xaml
<Entry
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Development workflow for Docker apps
description: Learn details of the workflow for developing Docker-based applications. Optimize Dockerfiles and use the simplified workflow available in Visual Studio.
ms.date: 11/19/2021
ms.date: 09/10/2024
---
# Development workflow for Docker apps

Expand Down Expand Up @@ -379,12 +379,14 @@ services:
sqldata:
image: mcr.microsoft.com/mssql/server:latest
environment:
- SA_PASSWORD=Pass@word
- SA_PASSWORD=[PLACEHOLDER]
- ACCEPT_EULA=Y
ports:
- "5433:1433"
```

[!INCLUDE [managed-identities](../../../framework/includes/managed-identities.md)]

This docker-compose.yml file is a simplified and merged version. It contains static configuration data for each container (like the name of the custom image), which is always required, and configuration information that might depend on the deployment environment, like the connection string. In later sections, you will learn how to split the docker-compose.yml configuration into multiple docker-compose files and override values depending on the environment and execution type (debug or release).

The docker-compose.yml file example defines four services: the `webmvc` service (a web application), two microservices (`ordering-api` and `basket-api`), and one data source container, `sqldata`, based on SQL Server for Linux running as a container. Each service will be deployed as a container, so a Docker image is required for each.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Implement resilient Entity Framework Core SQL connections
description: Learn how to implement resilient Entity Framework Core SQL connections. This technique is especially important when using Azure SQL Database in the cloud.
ms.date: 10/16/2018
ms.date: 09/10/2024
---
# Implement resilient Entity Framework Core SQL connections

Expand All @@ -16,17 +16,20 @@ For instance, the following code at the EF Core connection level enables resilie
// Other code ...
builder.Services.AddDbContext<CatalogContext>(options =>
{
options.UseSqlServer(builder.Configuration["ConnectionString"],
sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.EnableRetryOnFailure(
maxRetryCount: 10,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null);
});
options.UseSqlServer(
builder.Configuration["ConnectionString"],
sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.EnableRetryOnFailure(
maxRetryCount: 10,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null);
});
});
```

[!INCLUDE [managed-identities](../../../framework/includes/managed-identities.md)]

## Execution strategies and explicit transactions using BeginTransaction and multiple DbContexts

When retries are enabled in EF Core connections, each operation you perform using EF Core becomes its own retryable operation. Each query and each call to `SaveChanges` will be retried as a unit if a transient failure occurs.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Health monitoring
description: Explore one way of implementing health monitoring.
ms.date: 06/23/2021
ms.date: 09/10/2024
---
# Health monitoring

Expand Down Expand Up @@ -97,6 +97,8 @@ public class SqlConnectionHealthCheck : IHealthCheck
}
```

[!INCLUDE [managed-identities](../../../framework/includes/managed-identities.md)]

Note that in the previous code, `Select 1` is the query used to check the Health of the database. To monitor the availability of your microservices, orchestrators like Kubernetes periodically perform health checks by sending requests to test the microservices. It's important to keep your database queries efficient so that these operations are quick and don’t result in a higher utilization of resources.

Finally, add a middleware that responds to the url path `/hc`:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ using System.Collections.Generic;

public class OrderQueries : IOrderQueries
{
public async Task<IEnumerable<OrderSummary>> GetOrdersAsync()
public async Task<IEnumerable<OrderSummary>> GetOrdersAsync()
{
using (var connection = new SqlConnection(_connectionString))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Using NoSQL databases as a persistence infrastructure
description: Understand the use of NoSql databases in general, and Azure Cosmos DB in particular, as an option to implement persistence.
ms.date: 06/23/2021
ms.date: 09/10/2024
---
# Use NoSQL databases as a persistence infrastructure

Expand Down Expand Up @@ -275,6 +275,8 @@ services:
- ConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosqldata}
```

[!INCLUDE [managed-identities](../../../framework/includes/managed-identities.md)]

The `ConnectionString` environment variable is resolved this way: If the `ESHOP_AZURE_COSMOSDB` global variable is defined in the `.env` file with the Azure Cosmos DB connection string, it will use it to access the Azure Cosmos DB database in the cloud. If it’s not defined, it will take the `mongodb://nosqldata` value and use the development MongoDB container.

The following code shows the `.env` file with the Azure Cosmos DB connection string global environment variable, as implemented in eShopOnContainers:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Creating a simple data-driven CRUD microservice
description: .NET Microservices Architecture for Containerized .NET Applications | Understand the creation of a simple CRUD (data-driven) microservice within the context of a microservices application.
ms.date: 03/04/2024
ms.date: 09/10/2024
---

# Creating a simple data-driven CRUD microservice
Expand Down Expand Up @@ -211,6 +211,8 @@ builder.Services.AddDbContext<CatalogContext>(options =>
});
```

[!INCLUDE [managed-identities](../../../framework/includes/managed-identities.md)]

### Additional resources

- **Querying Data** \
Expand Down Expand Up @@ -254,9 +256,11 @@ catalog-api:
- "5101:80"
```

[!INCLUDE [managed-identities](../../../framework/includes/managed-identities.md)]

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.
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](https://azure.microsoft.com/services/key-vault/).

Expand All @@ -275,9 +279,7 @@ As business requirements change, new collections of resources may be added, the
Versioning enables a Web API to indicate the features and resources that it exposes. A client application can then submit requests to a specific version of a feature or resource. There are several approaches to implement versioning:

- URI versioning

- Query string versioning

- Header versioning

Query string and URI versioning are the simplest to implement. Header versioning is a good approach. However, header versioning is not as explicit and straightforward as URI versioning. Because URL versioning is the simplest and most explicit, the eShopOnContainers sample application uses URI versioning.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ services:
- "5672:5672"
sqldata:
environment:
- SA_PASSWORD=Pass@word
- SA_PASSWORD=[PLACEHOLDER]
- ACCEPT_EULA=Y
ports:
- "5433:1433"
Expand All @@ -185,6 +185,8 @@ services:
- "27017:27017"
```

[!INCLUDE [managed-identities](../../../framework/includes/managed-identities.md)]

So, to run the functional/integration tests you must first run this command, from the solution test folder:

```console
Expand Down
Loading
Loading