diff --git a/.github/workflows/check-for-build-warnings.yml b/.github/workflows/check-for-build-warnings.yml
index 23aa86c311cc8..c8d6e352a13ea 100644
--- a/.github/workflows/check-for-build-warnings.yml
+++ b/.github/workflows/check-for-build-warnings.yml
@@ -13,7 +13,7 @@ jobs:
issues: write
pull-requests: write
steps:
- - uses: actions/checkout@v4.1.5
+ - uses: actions/checkout@v4.1.7
with:
ref: ${{ github.event.pull_request.head.sha }}
diff --git a/.github/workflows/clean-repo.yml b/.github/workflows/clean-repo.yml
index 538438596e039..f7ed4faf00374 100644
--- a/.github/workflows/clean-repo.yml
+++ b/.github/workflows/clean-repo.yml
@@ -14,7 +14,7 @@ jobs:
pull-requests: write
steps:
- - uses: actions/checkout@v4.1.5
+ - uses: actions/checkout@v4.1.7
# Call clean repo
- name: Clean repo
diff --git a/.github/workflows/dependabot-bot.yml b/.github/workflows/dependabot-bot.yml
index 0f9e707adadfa..0c8f434f1b873 100644
--- a/.github/workflows/dependabot-bot.yml
+++ b/.github/workflows/dependabot-bot.yml
@@ -22,7 +22,7 @@ jobs:
# Checkout the repo into the workspace within the VM
steps:
- - uses: actions/checkout@v4.1.5
+ - uses: actions/checkout@v4.1.7
# - name: Setup .NET
# uses: actions/setup-dotnet@4d4a70f4a5b2a5a5329f13be4ac933f2c9206ac0
# with:
diff --git a/.github/workflows/docs-verifier-tryfix.yml b/.github/workflows/docs-verifier-tryfix.yml
index 29cabdc65095a..f42269b87ec4c 100644
--- a/.github/workflows/docs-verifier-tryfix.yml
+++ b/.github/workflows/docs-verifier-tryfix.yml
@@ -30,7 +30,7 @@ jobs:
core.setFailed(`Request failed with error ${err}`)
}
- name: Checkout the repository
- uses: actions/checkout@v4.1.5
+ uses: actions/checkout@v4.1.7
- name: Checkout Pull Request
run: |
diff --git a/.github/workflows/docs-verifier.yml b/.github/workflows/docs-verifier.yml
index cab490569dddf..b9e13a557ea4e 100644
--- a/.github/workflows/docs-verifier.yml
+++ b/.github/workflows/docs-verifier.yml
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
- uses: actions/checkout@v4.1.5
+ uses: actions/checkout@v4.1.7
- name: Validate
uses: dotnet/docs-actions/actions/docs-verifier@main
diff --git a/.github/workflows/markdownlint.yml b/.github/workflows/markdownlint.yml
index baaad5c3da783..51c5d49f0c38f 100644
--- a/.github/workflows/markdownlint.yml
+++ b/.github/workflows/markdownlint.yml
@@ -23,7 +23,7 @@ jobs:
statuses: write
steps:
- - uses: actions/checkout@v4.1.5
+ - uses: actions/checkout@v4.1.7
- name: Use Node.js
uses: actions/setup-node@eff380dfbcf941bf8832e4acb788cebe13dfd758
with:
diff --git a/.github/workflows/snippets5000.yml b/.github/workflows/snippets5000.yml
index 91dc1ac17c28b..a1b0b95f123ba 100644
--- a/.github/workflows/snippets5000.yml
+++ b/.github/workflows/snippets5000.yml
@@ -28,7 +28,7 @@ jobs:
steps:
# Checkout the repository for the PR
- name: Checkout repository
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b #@v4.1.5
+ uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #@v4.1.7
# Get the latest preview SDK (or sdk not installed by the runner)
- name: Setup .NET
diff --git a/.github/workflows/whats-new.yml b/.github/workflows/whats-new.yml
index 3654b6722a5d0..f1d77ac3b9c88 100644
--- a/.github/workflows/whats-new.yml
+++ b/.github/workflows/whats-new.yml
@@ -19,7 +19,7 @@ jobs:
pull-requests: write
steps:
- - uses: actions/checkout@v4.1.5
+ - uses: actions/checkout@v4.1.7
- name: "Print manual run reason"
if: ${{ github.event_name == 'workflow_dispatch' }}
diff --git a/.openpublishing.redirection.core.json b/.openpublishing.redirection.core.json
index d49ffecc4532c..6ff6513ca5bb6 100644
--- a/.openpublishing.redirection.core.json
+++ b/.openpublishing.redirection.core.json
@@ -701,13 +701,17 @@
"source_path_from_root": "/docs/core/install/dependencies.md",
"redirect_url": "/dotnet/core/install/windows"
},
+ {
+ "source_path_from_root": "/docs/core/install/linux-centos.md",
+ "redirect_url": "/dotnet/core/install/linux-rhel#where-is-centos-linux"
+ },
{
"source_path_from_root": "/docs/core/install/linux-package-manager-centos7.md",
- "redirect_url": "/dotnet/core/install/linux-centos"
+ "redirect_url": "/dotnet/core/install/linux-rhel#where-is-centos-linux"
},
{
"source_path_from_root": "/docs/core/install/linux-package-manager-centos8.md",
- "redirect_url": "/dotnet/core/install/linux-centos"
+ "redirect_url": "/dotnet/core/install/linux-rhel#where-is-centos-linux"
},
{
"source_path_from_root": "/docs/core/install/linux-package-manager-debian10.md",
diff --git a/docs/ai/how-to/snippets/semantic-kernel/semantic-kernel.csproj b/docs/ai/how-to/snippets/semantic-kernel/semantic-kernel.csproj
index 18a9242654133..7edb8ec7085ef 100644
--- a/docs/ai/how-to/snippets/semantic-kernel/semantic-kernel.csproj
+++ b/docs/ai/how-to/snippets/semantic-kernel/semantic-kernel.csproj
@@ -19,7 +19,7 @@
-
+
diff --git a/docs/architecture/blazor-for-web-forms-developers/components.md b/docs/architecture/blazor-for-web-forms-developers/components.md
index 03c284e4b77e5..b286a9ddb7361 100644
--- a/docs/architecture/blazor-for-web-forms-developers/components.md
+++ b/docs/architecture/blazor-for-web-forms-developers/components.md
@@ -269,7 +269,7 @@ public partial class Counter : System.Web.UI.UserControl
}
```
-In Blazor, you can register handlers for DOM UI events directly `using` directive attributes of the form `@on{event}`. The `{event}` placeholder represents the name of the event. For example, you can listen for button clicks like this:
+In Blazor, you can register handlers for DOM UI events directly using directive attributes of the form `@on{event}`. The `{event}` placeholder represents the name of the event. For example, you can listen for button clicks like this:
```razor
diff --git a/docs/architecture/maui/accessing-remote-data.md b/docs/architecture/maui/accessing-remote-data.md
index 334f11f9760c2..a10d762a99d10 100644
--- a/docs/architecture/maui/accessing-remote-data.md
+++ b/docs/architecture/maui/accessing-remote-data.md
@@ -296,7 +296,7 @@ Distributed applications, such as the eShop reference application, should provid
- A shared cache, which can be accessed by multiple processes or machines.
- A private cache, where data is held locally on the device running the app.
-The eShop multi-platform app uses a private cache, where data is held locally on the device that's running an instance of the app. For information about the cache used by the eShop reference application, see [.NET Microservices: Architecture for Containerized .NET Applications](https://aka.ms/microservicesebook).
+The eShop multi-platform app uses a private cache, where data is held locally on the device that's running an instance of the app.
> [!TIP]
> Think of the cache as a transient data store that could disappear at any time.
@@ -352,7 +352,7 @@ If a request still fails after a number of retries, it's better for the app to p
Use a finite number of retries, or implement the [Circuit Breaker](/azure/architecture/patterns/circuit-breaker) pattern to allow a service to recover.
-The eShop reference application does implement the retry pattern. For more information, including a discussion of how to combine the retry pattern with the HttpClient class, see [.NET Microservices: Architecture for Containerized .NET Applications](https://aka.ms/microservicesebook).
+The eShop reference application does implement the retry pattern.
For more information about the retry pattern, see the [Retry](/azure/architecture/patterns/retry) pattern on Microsoft Docs.
@@ -367,7 +367,7 @@ The circuit breaker pattern can prevent an app from repeatedly trying to execute
A circuit breaker acts as a proxy for operations that might fail. The proxy should monitor the number of recent failures that have occurred, and use this information to decide whether to allow the operation to proceed, or to return an exception immediately.
-The eShop multi-platform app does not currently implement the circuit breaker pattern. However, the eShop does. For more information, see [.NET Microservices: Architecture for Containerized .NET Applications](https://aka.ms/microservicesebook).
+The eShop multi-platform app does not currently implement the circuit breaker pattern. However, the eShop does.
> [!TIP]
> Combine the retry and circuit breaker patterns.
diff --git a/docs/architecture/maui/authentication-and-authorization.md b/docs/architecture/maui/authentication-and-authorization.md
index 3cb6fec7c65e7..d3b725fe761b6 100644
--- a/docs/architecture/maui/authentication-and-authorization.md
+++ b/docs/architecture/maui/authentication-and-authorization.md
@@ -12,7 +12,7 @@ ms.date: 05/30/2024
Authentication is the process of obtaining identification credentials such as name and password from a user and validating those credentials against an authority. The entity that submitted the credentials is considered an authenticated identity if the credentials are valid. Once an identity has been established, an authorization process determines whether that identity has access to a given resource.
-There are many approaches to integrating authentication and authorization into a .NET MAUI app that communicates with an ASP.NET web application, including using ASP.NET Core Identity, external authentication providers such as Microsoft, Google, Facebook, or Twitter, and authentication middleware. The eShop multi-platform app performs authentication and authorization with a containerized identity microservice that uses IdentityServer 4. The app requests security tokens from IdentityServer to authenticate a user or access a resource. For IdentityServer to issue tokens on behalf of a user, the user must sign in to IdentityServer. However, IdentityServer doesn't provide a user interface or database for authentication. Therefore, in the eShop reference application, ASP.NET Core Identity is used for this purpose.
+There are many approaches to integrating authentication and authorization into a .NET MAUI app that communicates with an ASP.NET web application, including using ASP.NET Core Identity, external authentication providers such as Microsoft, Google, Facebook, or Twitter, and authentication middleware. The eShop multi-platform app performs authentication and authorization with a containerized identity microservice that uses IdentityServer. The app requests security tokens from IdentityServer to authenticate a user or access a resource. For IdentityServer to issue tokens on behalf of a user, the user must sign in to IdentityServer. However, IdentityServer doesn't provide a user interface or database for authentication. Therefore, in the eShop reference application, ASP.NET Core Identity is used for this purpose.
## Authentication
@@ -20,39 +20,39 @@ Authentication is required when an application needs to know the current user's
For authentication scenarios that use a local user datastore and persist identity information between requests via cookies (as is typical in ASP.NET web applications), ASP.NET Core Identity is a suitable solution. However, cookies are not always a natural means of persisting and transmitting data. For example, an ASP.NET Core web application that exposes RESTful endpoints that are accessed from an app will typically need to use bearer token authentication since cookies can't be used in this scenario. However, bearer tokens can easily be retrieved and included in the authorization header of web requests made from the app.
-### Issuing bearer tokens using IdentityServer 4
+### Issuing bearer tokens using IdentityServer
-[IdentityServer 4](https://github.com/IdentityServer/IdentityServer4) is an open source OpenID Connect and OAuth 2.0 framework for ASP.NET Core, which can be used for many authentication and authorization scenarios, including issuing security tokens for local ASP.NET Core Identity users.
+[IdentityServer](https://github.com/DuendeSoftware/IdentityServer) is an open-source OpenID Connect and OAuth 2.0 framework for ASP.NET Core, which can be used for many authentication and authorization scenarios, including issuing security tokens for local ASP.NET Core Identity users.
> [!NOTE]
> OpenID Connect and OAuth 2.0 are very similar, while having different responsibilities.
OpenID Connect is an authentication layer on top of the OAuth 2.0 protocol. OAuth 2 is a protocol that allows applications to request access tokens from a security token service and use them to communicate with APIs. This delegation reduces complexity in both client applications and APIs since authentication and authorization can be centralized.
-OpenID Connect and OAuth 2.0 combine the two fundamental security concerns of authentication and API access, and IdentityServer 4 is an implementation of these protocols.
+OpenID Connect and OAuth 2.0 combine the two fundamental security concerns of authentication and API access, and IdentityServer is an implementation of these protocols.
In applications that use direct client-to-microservice communication, such as the eShop reference application, a dedicated authentication microservice acting as a Security Token Service (STS) can be used to authenticate users, as shown in the following diagram. For more information about direct client-to-microservice communication, see [Microservices](micro-services.md).
![Authentication by a dedicated authentication microservice.](./media/authentication-dedicated-authentication-microservice.png)
-The eShop multi-platform app communicates with the identity microservice, which uses IdentityServer 4 to perform authentication, and access control for APIs. Therefore, the multi-platform app requests tokens from IdentityServer, either for authenticating a user or for accessing a resource:
+The eShop multi-platform app communicates with the identity microservice, which uses IdentityServer to perform authentication, and access control for APIs. Therefore, the multi-platform app requests tokens from IdentityServer, either for authenticating a user or for accessing a resource:
- Authenticating users with IdentityServer is achieved by the multi-platform app requesting an _identity_ token, representing an authentication process's outcome. At a minimum, it contains an identifier for the user and information about how and when the user is authenticated. It can also include additional identity data.
- Accessing a resource with IdentityServer is achieved by the multi-platform app requesting an _access_ token, which allows access to an API resource. Clients request access tokens and forward them to the API. Access tokens contain information about the client and the user, if present. APIs then use that information to authorize access to their data.
> [!NOTE]
-> A client must be registered with IdentityServer before it can successfully request tokens. For more information on adding clients, see [Defining Clients](https://identityserver4.readthedocs.io/en/latest/topics/clients.html).
+> A client must be registered with IdentityServer before it can successfully request tokens. For more information on adding clients, see [Defining Clients](https://docs.duendesoftware.com/identityserver/v7/quickstarts/1_client_credentials/#define-client).
### Adding IdentityServer to a web application
-In order for an ASP.NET Core web application to use IdentityServer 4, it must be added to the web application's Visual Studio solution. For more information, see [Setup and Overview](https://identityserver4.readthedocs.io/en/latest/quickstarts/0_overview.html) 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 achieved in the `Configure` method in the web application's `Startup` class, as demonstrated in the following code example:
+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:
```csharp
-public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
-{
- app.UseIdentity();
-}
+
+...
+
+app.UseIdentityServer();
```
Order matters in the web application's HTTP request processing pipeline. Therefore, IdentityServer must be added to the pipeline before the UI framework that implements the login screen.
@@ -86,9 +86,9 @@ After calling the `services.AddIdentityServer` method, additional fluent APIs ar
- ASP.NET Core Identity.
> [!TIP]
-> Dynamically load the IdentityServer 4 configuration. IdentityServer 4's APIs allow for configuring IdentityServer from an in-memory list of configuration objects. In the eShop reference application, these in-memory collections are hard-coded into the application. However, in production scenarios they can be loaded dynamically from a configuration file or from a database.
+> Dynamically load the IdentityServer configuration. IdentityServer's APIs allow for configuring IdentityServer from an in-memory list of configuration objects. In the eShop reference application, these in-memory collections are hard-coded into the application. However, in production scenarios they can be loaded dynamically from a configuration file or from a database.
-For information about configuring IdentityServer to use ASP.NET Core Identity, see [Using ASP.NET Core Identity](https://identityserver4.readthedocs.io/en/latest/quickstarts/6_aspnet_identity.html) in the IdentityServer documentation.
+For information about configuring IdentityServer to use ASP.NET Core Identity, see [Using ASP.NET Core Identity](https://docs.duendesoftware.com/identityserver/v7/quickstarts/5_aspnetid/) in the IdentityServer documentation.
### Configuring API resources
@@ -99,13 +99,14 @@ public static IEnumerable GetApis()
{
return new List
{
- new ApiResource("orders", "Orders Service"),
- new ApiResource("basket", "Basket Service")
+ new ApiScope("orders", "Orders Service"),
+ new ApiScope("basket", "Basket Service"),
+ new ApiScope("webhooks", "Webhooks registration Service"),
};
}
```
-This method specifies that IdentityServer should protect the orders and basket APIs. Therefore, IdentityServer-managed access tokens will be required when making calls to these APIs. For more information about the `ApiResource` type, see [API Resource](https://identityserver4.readthedocs.io/en/latest/reference/api_resource.html#refapiresource) in the IdentityServer 4 documentation.
+This method specifies that IdentityServer should protect the orders and basket APIs. Therefore, IdentityServer-managed access tokens will be required when making calls to these APIs. For more information about the `ApiResource` type, see [API Resource](https://docs.duendesoftware.com/identityserver/v7/fundamentals/resources/api_resources/) in the IdentityServer documentation.
### Configuring identity resources
@@ -127,7 +128,7 @@ The OpenID Connect specification specifies some [standard identity resources](ht
> [!NOTE]
> The IdentityResources class supports all of the scopes defined in the OpenID Connect specification (openid, email, profile, telephone, and address).
-IdentityServer also supports defining custom identity resources. For more information, see [Defining custom identity resources](https://identityserver4.readthedocs.io/en/latest/topics/resources.html#defining-custom-identity-resources) in the IdentityServer documentation. For more information about the IdentityResource type, see [Identity Resource](https://identityserver4.readthedocs.io/en/latest/reference/identity_resource.html) in the IdentityServer 4 documentation.
+IdentityServer also supports defining custom identity resources. For more information, see [Defining custom identity resources](https://identityserver4.readthedocs.io/en/latest/topics/resources.html#defining-custom-identity-resources) in the IdentityServer documentation. For more information about the IdentityResource type, see [Identity Resource](https://docs.duendesoftware.com/identityserver/v7/fundamentals/resources/identity/) in the IdentityServer documentation.
### Configuring clients
@@ -148,18 +149,18 @@ public static IEnumerable GetClients(Dictionary clien
// Omitted for brevity
new Client
{
- ClientId = "xamarin",
- ClientName = "eShop Xamarin OpenId Client",
+ ClientId = "maui",
+ ClientName = "eShop .NET MAUI OpenId Client",
AllowedGrantTypes = GrantTypes.Hybrid,
ClientSecrets =
{
new Secret("secret".Sha256())
},
- RedirectUris = { clientsUrl["Xamarin"] },
+ RedirectUris = { clientsUrl["maui"] },
RequireConsent = false,
RequirePkce = true,
- PostLogoutRedirectUris = { $"{clientsUrl["Xamarin"]}/Account/Redirecting" },
- AllowedCorsOrigins = { "http://eshopxamarin" },
+ PostLogoutRedirectUris = { $"{clientsUrl["maui"]}/Account/Redirecting" },
+ AllowedCorsOrigins = { "http://eshopmaui" },
AllowedScopes = new List
{
IdentityServerConstants.StandardScopes.OpenId,
@@ -169,8 +170,10 @@ public static IEnumerable GetClients(Dictionary clien
"basket"
},
AllowOfflineAccess = true,
- AllowAccessTokensViaBrowser = true
- },
+ AllowAccessTokensViaBrowser = true,
+ AccessTokenLifetime = 60 * 60 * 2, // 2 hours
+ IdentityTokenLifetime = 60 * 60 * 2 // 2 hours
+ }
};
}
```
@@ -190,6 +193,10 @@ This configuration specifies data for the following properties:
| `AllowedCorsOrigins` | Specifies the origin of the client so that IdentityServer can allow cross-origin calls from the origin. |
| `AllowedScopes` | Specifies the resources the client has access to. By default, a client has no access to any resources. |
| `AllowOfflineAccess` | Specifies whether the client can request refresh tokens. |
+| `AllowAccessTokensViaBrowser` | Specifies whether the client can receive access tokens from a browser window. |
+| `AlwaysIncludeUserClaimsInIdToken` | Specifies that the user claims will always be added to the id token. By default, these would have to be retrieved using the `userinfo` endpoint. |
+| `AccessTokenLifetime` | Specifies the lifetime of the access token in seconds. |
+| `IdentityTokenLifetime` | Specifies the lifetime of the identity token in seconds. |
### Configuring the authentication flow
@@ -204,7 +211,7 @@ The authentication flow between a client and IdentityServer can be configured by
> [!TIP]
> Consider using the hybrid authentication flow. The hybrid authentication flow mitigates a number of attacks that apply to the browser channel, and is the recommended flow for native applications that want to retrieve access tokens (and possibly refresh tokens).
-For more information about authentication flows, see [Grant Types](https://identityserver4.readthedocs.io/en/latest/topics/grant_types.html) in the IdentityServer 4 documentation.
+For more information about authentication flows, see [Grant Types](https://docs.duendesoftware.com/identityserver/v7/data/operational/grants/) in the IdentityServer documentation.
### Performing authentication
@@ -220,100 +227,64 @@ The eShop multi-platform app signs out of IdentityServer by sending a request to
![High-level overview of the sign out process.](./media/high-level-overview-sign-out-process.png)
-In the eShop multi-platform app, communication with IdentityServer is performed by the `IdentityService` class, which implements the `IIdentityService` interface. This interface specifies that the implementing class must provide `CreateAuthorizationRequest`, `CreateLogoutRequest`, and `GetTokenAsync` methods.
+In the eShop multi-platform app, communication with IdentityServer is performed by the `IdentityService` class, which implements the `IIdentityService` interface. This interface specifies that the implementing class must provide `SignInAsync`, `SignOutAsync`, `GetUserInfoAsync` and `GetAuthTokenAsync` methods.
### Signing-in
When the user taps the `LOGIN` button on the `LoginView`, the `SignInCommand` in the `LoginViewModel` class is executed, which in turn executes the `SignInAsync` method. The following code example shows this method:
```csharp
+[RelayCommand]
private async Task SignInAsync()
{
await IsBusyFor(
async () =>
{
- LoginUrl = _identityService.CreateAuthorizationRequest();
+ var loginSuccess = await _appEnvironmentService.IdentityService.SignInAsync();
- IsValid = true;
- IsLogin = true;
+ if (loginSuccess)
+ {
+ await NavigationService.NavigateToAsync("//Main/Catalog");
+ }
});
}
```
-This method invokes the `CreateAuthorizationRequest` method in the `IdentityService` class, as shown in the following code example:
-
-```csharp
-public string CreateAuthorizationRequest()
-{
- // Create URI to authorization endpoint
- var authorizeRequest = new AuthorizeRequest(GlobalSetting.Instance.IdentityEndpoint);
- // Dictionary with values for the authorize request
- var dic = new Dictionary();
- dic.Add("client_id", GlobalSetting.Instance.ClientId);
- dic.Add("client_secret", GlobalSetting.Instance.ClientSecret);
- dic.Add("response_type", "code id_token");
- dic.Add("scope", "openid profile basket orders locations marketing offline_access");
- dic.Add("redirect_uri", GlobalSetting.Instance.IdentityCallback);
- dic.Add("nonce", Guid.NewGuid().ToString("N"));
- dic.Add("code_challenge", CreateCodeChallenge());
- dic.Add("code_challenge_method", "S256");
- // Add CSRF token to protect against cross-site request forgery attacks.
- var currentCSRFToken = Guid.NewGuid().ToString("N");
- dic.Add("state", currentCSRFToken);
-
- var authorizeUri = authorizeRequest.Create(dic);
- return authorizeUri;
-}
-```
-
-This method creates the URI for IdentityServer's [authorization endpoint](https://identityserver4.readthedocs.io/en/latest/endpoints/authorize.html) with the required parameters. The authorization endpoint is at `/connect/authorize` on port 5105 of the base endpoint exposed as a user setting. For more information about user settings, see [Configuration Management](app-settings-management.md).
-
-> [!NOTE]
-> The attack surface of the eShop multi-platform app is reduced by implementing the Proof Key for Code Exchange (PKCE) extension to OAuth. PKCE protects the authorization code from being used if it's intercepted. This is achieved by the client generating a secret verifier, a hash of which is passed in the authorization request, and which is presented unhashed when redeeming the authorization code. For more information about PKCE, see [Proof Key for Code Exchange by OAuth Public Clients](https://tools.ietf.org/html/rfc7636) on the Internet Engineering Task Force web site.
-
-The returned URI is stored in the `LoginUrl` property of the `LoginViewModel` class. When the `IsLogin` property becomes true, the `WebView` in the `LoginView` becomes visible. The `WebView` data binds its `Source` property to the `LoginUrl` property of the `LoginViewModel` class and a sign-in request to IdentityServer when the `LoginUrl` property is set to IdentityServer's authorization endpoint. When IdentityServer receives this request and the user isn't authenticated, the `WebView` will be redirected to the configured login page shown in the image below.
-
-![Login page displayed by the WebView.](./media/login-page-displayed-by-the-webview.png)
-
-Once login is completed, the `WebView` will be redirected to a return URI. This `WebView` navigation will cause the `NavigateAsync` method in the `LoginViewModel` class to be executed, as shown in the following code example:
+This method invokes the `SignInAsync` method in the `IdentityService` class, as shown in the following code example:
```csharp
-private async Task NavigateAsync(string url)
+public async Task SignInAsync()
{
- var unescapedUrl = System.Net.WebUtility.UrlDecode(url);
+ var response = await GetClient().LoginAsync(new LoginRequest()).ConfigureAwait(false);
- if (unescapedUrl.Equals(GlobalSetting.Instance.LogoutCallback, StringComparison.OrdinalIgnoreCase))
+ if (response.IsError)
{
- _settingsService.AuthAccessToken = string.Empty;
- _settingsService.AuthIdToken = string.Empty;
- IsLogin = false;
- LoginUrl = _identityService.CreateAuthorizationRequest();
+ return false;
}
- else if (unescapedUrl.Contains(GlobalSetting.Instance.Callback, StringComparison.OrdinalIgnoreCase))
- {
- var authResponse = new AuthorizeResponse(url);
- if (!string.IsNullOrWhiteSpace(authResponse.Code))
- {
- var userToken = await _identityService.GetTokenAsync(authResponse.Code);
- string accessToken = userToken.AccessToken;
- if (!string.IsNullOrWhiteSpace(accessToken))
+ await _settingsService
+ .SetUserTokenAsync(
+ new UserToken
{
- _settingsService.AuthAccessToken = accessToken;
- _settingsService.AuthIdToken = authResponse.IdentityToken;
- await NavigationService.NavigateToAsync("//Main/Catalog");
- }
- }
- }
+ AccessToken = response.AccessToken,
+ IdToken = response.IdentityToken,
+ RefreshToken = response.RefreshToken,
+ ExpiresAt = response.AccessTokenExpiration
+ })
+ .ConfigureAwait(false);
+
+ return !response.IsError;
}
```
-This method parses the authentication response contained in the return URI, and provided that a valid authorization code is present, it makes a request to IdentityServer's [token endpoint](https://identityserver4.readthedocs.io/en/latest/endpoints/token.html), passing the authorization code, the PKCE secret verifier, and other required parameters. The token endpoint is at `/connect/token` on port 5105 of the base endpoint exposed as a user setting. For more information about user settings, see [Configuration management](app-settings-management.md)).
+The `IdentityService` makes use of the `OidcClient` provided with the `IdentityModel.OidcClient` NuGet package. This client displays the authentication web view to the user in the application and captures the authentication result. The client connects to the URI for IdentityServer's [authorization endpoint](https://docs.duendesoftware.com/identityserver/v7/reference/endpoints/authorize/) with the required parameters. The authorization endpoint is at `/connect/authorize` on port 5105 of the base endpoint exposed as a user setting. For more information about user settings, see [Configuration Management](app-settings-management.md).
-> [!TIP]
-> Make sure to validate return URIs. Although the eShop multi-platform app doesn't validate the return URI, the best practice is to validate that the return URI refers to a known location in order to prevent open-redirect attacks.
+> [!NOTE]
+> The attack surface of the eShop multi-platform app is reduced by implementing the Proof Key for Code Exchange (PKCE) extension to OAuth. PKCE protects the authorization code from being used if it's intercepted. This is achieved by the client generating a secret verifier, a hash of which is passed in the authorization request, and which is presented unhashed when redeeming the authorization code. For more information about PKCE, see [Proof Key for Code Exchange by OAuth Public Clients](https://tools.ietf.org/html/rfc7636) on the Internet Engineering Task Force web site.
+
+![Login page displayed by the WebView.](./media/mobile-authentication.png)
-If the token endpoint receives a valid authorization code and PKCE secret verifier, it responds with an access token, identity token, and refresh token. The access token (which allows access to API resources) and identity token are stored as application settings, and page navigation is performed. Therefore, the overall effect in the eShop multi-platform app is this: provided that users are able to successfully authenticate with IdentityServer, they are navigated to the `//Main/Catalog` route, which is a `TabbedPage` that displays the `CatalogView` as its selected tab.
+If the token endpoint receives valid authentication information, authorization code, and PKCE secret verifier, it responds with an access token, identity token, and refresh token. The access token (which allows access to API resources) and identity token are stored as application settings, and page navigation is performed. Therefore, the overall effect in the eShop multi-platform app is this: provided that users are able to successfully authenticate with IdentityServer, they are navigated to the `//Main/Catalog` route, which is a `TabbedPage` that displays the `CatalogView` as its selected tab.
For information about page navigation, see [Navigation](navigation.md). For information about how WebView navigation causes a view model method to be executed, see [Invoking navigation using behaviors](navigation.md#invoking-navigation-using-behaviors). For information about application settings, see [Configuration management](app-settings-management.md).
@@ -322,64 +293,41 @@ For information about page navigation, see [Navigation](navigation.md). For info
### Signing-out
-When the user taps the `LOG OUT` button in the `ProfileView`, the `LogoutCommand` in the `ProfileViewModel` class is executed, which executes the `LogoutAsync` method. This method performs page navigation to the `LoginView` page, passing a `LogoutParameter` instance set to `true` as a parameter.
+When the user taps the `LOG OUT` button in the `ProfileView`, the `LogoutCommand` in the `ProfileViewModel` class is executed, which executes the `LogoutAsync` method. This method performs page navigation to the `LoginView` page, passing a `Logout` query parameter set to `true`.
-When a view is created and navigated to, the `InitializeAsync` method of the view's associated view model is executed, which then executes the `Logout` method of the `LoginViewModel` class, which is shown in the following code example:
+That parameter is evaluated in the `ApplyQueryAttributes` method. If the `Logout` parameter is present with a `true` value, the `PerformLogoutAsync` method of the `LoginViewModel` class is executed, which is shown in the following code example:
```csharp
-private void Logout()
+private async Task PerformLogoutAsync()
{
- var authIdToken = Settings.AuthIdToken;
- var logoutRequest = _identityService.CreateLogoutRequest(authIdToken);
-
- if (!string.IsNullOrEmpty(logoutRequest))
- {
- // Logout
- LoginUrl = logoutRequest;
- }
-
- // Omitted for brevity
-}
-```
+ await _appEnvironmentService.IdentityService.SignOutAsync();
-This method invokes the `CreateLogoutRequest` method in the `IdentityService` class, passing the identity token retrieved from application settings as a parameter. For more information about application settings, see [Configuration management](app-settings-management.md). The following code example shows the `CreateLogoutRequest` method:
+ _settingsService.UseFakeLocation = false;
-```csharp
-public string CreateLogoutRequest(string token)
-{
- // Omitted for brevity
-
- var (endpoint, callback) =
- (GlobalSetting.Instance.LogoutEndpoint, GlobalSetting.Instance.LogoutCallback);
-
- return $"{endpoint}?id_token_hint={token}&post_logout_redirect_uri={callback}";
+ UserName.Value = string.Empty;
+ Password.Value = string.Empty;
}
```
-This method creates the URI to IdentityServer's [end session endpoint](https://identityserver4.readthedocs.io/en/latest/endpoints/endsession.html#refendsession) with the required parameters. The end session endpoint is at `/connect/endsession` on port 5105 of the base endpoint exposed as a user setting.
-
-The returned URI is stored in the `LoginUrl` property of the `LoginViewModel` class. While the `IsLogin` property is true, the `WebView` in the `LoginView` is visible. The `WebView` data binds its `Source` property to the `LoginUrl` property of the `LoginViewModel` class, making a sign-out request to IdentityServer when the `LoginUrl` property is set to IdentityServer's end session endpoint. Sign-out occurs when IdentityServer receives this request, provided the user is signed in. Authentication is tracked with a cookie managed by the cookie authentication middleware from ASP.NET Core. Therefore, signing out of IdentityServer removes the authentication cookie and sends a post-logout redirect URI back to the client.
-
-The `WebView` will be redirected to the post-logout redirect URI in the multi-platform app. This `WebView` navigation will cause the `NavigateAsync` method in the `LoginViewModel` class to be executed, which is shown in the following code example:
+This method invokes the `SignOutAsync` method in the `IdentityService` class, which invokes the `OidcClient` to end the user's session and clears any saved user tokens. For more information about application settings, see [Configuration management](app-settings-management.md). The following code example shows the `SignOutAsync` method:
```csharp
-private async Task NavigateAsync(string url)
+public async Task SignOutAsync()
{
- var unescapedUrl = System.Net.WebUtility.UrlDecode(url);
+ var response = await GetClient().LogoutAsync(new LogoutRequest()).ConfigureAwait(false);
- if (unescapedUrl.Equals(GlobalSetting.Instance.LogoutCallback, StringComparison.OrdinalIgnoreCase))
+ if (response.IsError)
{
- _settingsService.AuthAccessToken = string.Empty;
- _settingsService.AuthIdToken = string.Empty;
- IsLogin = false;
- LoginUrl = _identityService.CreateAuthorizationRequest();
+ return false;
}
-
- // Omitted for brevity
+
+ await _settingsService.SetUserTokenAsync(default);
+
+ return !response.IsError;
}
```
-This method clears both the identity token and the access token from application settings. It sets the `IsLogin` property to false, which causes the `WebView` on the `LoginView` page to become invisible. Finally, the `LoginUrl` property is set to the URI of IdentityServer's [authorization endpoint](https://identityserver4.readthedocs.io/en/latest/endpoints/authorize.html), with the required parameters, in preparation for the next time the user initiates a sign-in.
+This method uses the `OidcClient` to call the URI to IdentityServer's [end session endpoint](https://docs.duendesoftware.com/identityserver/v7/reference/endpoints/end_session/) with the required parameters. The end session endpoint is at `/connect/endsession` on port 5105 of the base endpoint exposed as a user setting. Once the user has successfully signed out, `LoginView` is presented to the user, and any saved user information will be cleared.
For information about page navigation, see [Navigation](navigation.md). For information about how `WebView` navigation causes a view model method to be executed, see [Invoking navigation using behaviors](navigation.md#invoking-navigation-using-behaviors). For information about application settings, see [Configuration management](app-settings-management.md).
@@ -405,7 +353,7 @@ If an unauthorized user attempts to access a controller or action marked with th
> [!NOTE]
> Parameters can be specified on the Authorize attribute to restrict an API to specific users. For more information, see [ASP.NET Core Docs: Authorization](/aspnet/core/security/authorization/introduction).
-IdentityServer can be integrated into the authorization workflow so that the access tokens it provides control authorization. This approach is shown in the diagram below.
+IdentityServer can be integrated into the authorization workflow so that the access tokens provide control authorization. This approach is shown in the diagram below.
![Authorization by access token.](./media/authorization-by-access-token.png)
@@ -413,51 +361,85 @@ The eShop multi-platform app communicates with the identity microservice and req
## Configuring IdentityServer to perform authorization
-To perform authorization with IdentityServer, its authorization middleware must be added to the web application's HTTP request pipeline. The middleware is added in the `ConfigureAuth` method in the web application's `Startup` class, which is invoked from the `Configure` method and is demonstrated in the following code example from the eShop reference application:
+To perform authorization with IdentityServer, its authorization middleware must be added to the web application's HTTP request pipeline. The middleware is added in the `AddDefaultAuthentication` extension method, which is invoked from the `AddApplicationServices` method in the `Program` class and is demonstrated in the following code example from the eShop reference application:
```csharp
-protected virtual void ConfigureAuth(IApplicationBuilder app)
+public static IServiceCollection AddDefaultAuthentication(this IHostApplicationBuilder builder)
{
- var identityUrl = Configuration.GetValue("IdentityUrl");
- app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
+ var services = builder.Services;
+ var configuration = builder.Configuration;
+
+ var identitySection = configuration.GetSection("Identity");
+
+ if (!identitySection.Exists())
+ {
+ // No identity section, so no authentication
+ return services;
+ }
+
+ // prevent from mapping "sub" claim to nameidentifier.
+ JsonWebTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
+
+ services.AddAuthentication().AddJwtBearer(options =>
{
- Authority = identityUrl.ToString(),
- ScopeName = "basket",
- RequireHttpsMetadata = false,
+ var identityUrl = identitySection.GetRequiredValue("Url");
+ var audience = identitySection.GetRequiredValue("Audience");
+
+ options.Authority = identityUrl;
+ options.RequireHttpsMetadata = false;
+ options.Audience = audience;
+ options.TokenValidationParameters.ValidIssuers = [identityUrl];
+ options.TokenValidationParameters.ValidateAudience = false;
});
+
+ services.AddAuthorization();
+
+ return services;
}
```
This method ensures that the API can only be accessed with a valid access token. The middleware validates the incoming token to ensure that it's sent from a trusted issuer and validates that the token is valid to be used with the API that receives it. Therefore, browsing to the ordering or basket controller will return a `401 (unauthorized)` HTTP status code, indicating that an access token is required.
-> [!NOTE]
-> IdentityServer's authorization middleware must be added to the web application's HTTP request pipeline before adding MVC with `app.UseMvc()` or `app.UseMvcWithDefaultRoute()`.
-
## Making access requests to APIs
When making requests to the ordering and basket microservices, the access token obtained from IdentityServer during the authentication process must be included in the request, as shown in the following code example:
```csharp
-var authToken = Settings.AuthAccessToken;
-Order = await _ordersService.GetOrderAsync(order.OrderNumber, authToken);
+public async Task CreateOrderAsync(Models.Orders.Order newOrder)
+{
+ var authToken = await _identityService.GetAuthTokenAsync().ConfigureAwait(false);
+
+ if (string.IsNullOrEmpty(authToken))
+ {
+ return;
+ }
+
+ var uri = $"{UriHelper.CombineUri(_settingsService.GatewayOrdersEndpointBase, ApiUrlBase)}?api-version=1.0";
+
+ var success = await _requestProvider.PostAsync(uri, newOrder, authToken, "x-requestid").ConfigureAwait(false);
+}
```
-The access token is stored as an application setting and is retrieved from platform-specific storage and included in the call to the `GetOrderAsync` method in the `OrderService` class.
+The access token is stored with the `IIdentityService` implementation and can be retrieved using the `GetAuthTokenAsync` method.
Similarly, the access token must be included when sending data to an IdentityServer protected API, as shown in the following code example:
```csharp
-var authToken = Settings.AuthAccessToken;
-await _basketService.UpdateBasketAsync(
- new CustomerBasket
+public async Task ClearBasketAsync()
+{
+ var authToken = await _identityService.GetAuthTokenAsync().ConfigureAwait(false);
+
+ if (string.IsNullOrEmpty(authToken))
{
- BuyerId = userInfo.UserId,
- Items = BasketItems.ToList()
- },
- authToken);
+ return;
+ }
+
+ await GetBasketClient().DeleteBasketAsync(new DeleteBasketRequest(), CreateAuthenticationHeaders(authToken))
+ .ConfigureAwait(false);
+}
```
-The access token is retrieved from settings and included in the call to the `UpdateBasketAsync` method in the `BasketService` class.
+The access token is retrieved from the `IIdentityService` and included in the call to the `ClearBasketAsync` method in the `BasketService` class.
The `RequestProvider` class in the eShop multi-platform app uses the `HttpClient` class to make requests to the RESTful APIs exposed by the eShop reference application. When making requests to the ordering and basket APIs, which require authorization, a valid access token must be included with the request. This is achieved by adding the access token to the headers of the HttpClient instance, as demonstrated in the following code example:
@@ -471,6 +453,6 @@ For more information about how the eShop multi-platform app makes web requests,
## Summary
-There are many approaches to integrating authentication and authorization into a .NET MAUI app that communicates with an ASP.NET web application. The eShop multi-platform app performs authentication and authorization with a containerized identity microservice that uses IdentityServer 4. IdentityServer is an open source OpenID Connect and OAuth 2.0 framework for ASP.NET Core that integrates with ASP.NET Core Identity to perform bearer token authentication.
+There are many approaches to integrating authentication and authorization into a .NET MAUI app that communicates with an ASP.NET web application. The eShop multi-platform app performs authentication and authorization with a containerized identity microservice that uses IdentityServer. IdentityServer is an open-source OpenID Connect and OAuth 2.0 framework for ASP.NET Core that integrates with ASP.NET Core Identity to perform bearer token authentication.
The multi-platform app requests security tokens from IdentityServer to authenticate a user or access a resource. When accessing a resource, an access token must be included in the request to APIs that require authorization. IdentityServer's middleware validates incoming access tokens to ensure that they are sent from a trusted issuer and that they are valid to be used with the API that receives them.
diff --git a/docs/architecture/maui/index.md b/docs/architecture/maui/index.md
index 7316fc0fe3717..6e475bdbffc0b 100644
--- a/docs/architecture/maui/index.md
+++ b/docs/architecture/maui/index.md
@@ -64,11 +64,11 @@ This book is for .NET MAUI developers that are already familiar with the framewo
## How to use the book
-This book focuses on building cross-platform enterprise apps using .NET MAUI. As such, it should be read in its entirety to provide a foundation of understanding such apps and their technical considerations. The book, along with its sample app, can also serve as a starting point or reference for creating a new enterprise app. Use the associated sample app as a template for the new app, or to see how to organize an app's component parts. Then, refer back to this guide for architectural guidance. You can find the sample app on [GitHub](https://github.com/dotnet-architecture/eshop-mobile-client).
+This book focuses on building cross-platform enterprise apps using .NET MAUI. As such, it should be read in its entirety to provide a foundation of understanding such apps and their technical considerations. The book, along with its sample app, can also serve as a starting point or reference for creating a new enterprise app. Use the associated sample app as a template for the new app, or to see how to organize an app's component parts. Then, refer back to this guide for architectural guidance. You can find the sample app on [GitHub](https://github.com/dotnet/eshop).
## What this book doesn't cover
-This book is aimed at readers who are already familiar with .NET MAUI. It does cover some concepts of .NET MAUI to help better illustrate the topic, but it does not cover most controls and concepts in any detail. For general guidance on building a new .NET MAUI app, please refer to the [Building your first app](/dotnet/maui/get-started/first-app) guide in the .NET MAUI Documentation
+This book is aimed at readers who are already familiar with .NET MAUI. It does cover some concepts of .NET MAUI to help better illustrate the topic, but it does not cover most controls and concepts in any detail. For general guidance on building a new .NET MAUI app, please refer to the [Building your first app](/dotnet/maui/get-started/first-app) guide in the .NET MAUI documentation.
### Additional resources
diff --git a/docs/architecture/maui/introduction.md b/docs/architecture/maui/introduction.md
index 8436188f638c6..c25cea69dbd6b 100644
--- a/docs/architecture/maui/introduction.md
+++ b/docs/architecture/maui/introduction.md
@@ -58,13 +58,11 @@ Below is a high-level overview of the architecture of the sample application.
![eShop high-level architecture](./media/high-level-architecture-diagram.png)
-The sample application ships with three client apps:
+The sample application ships with:
-- An MVC application developed with ASP.NET Core.
-- A Single Page Application (SPA) developed with Angular 2 and Typescript. This approach for web applications avoids performing a round-trip to the server with each operation.
-- A multi-platform app developed with .NET MAUI, which supports iOS, Android, macOS via Mac Catalyst, and Windows 10/11.
-
-For information about the web applications, see [Architecting and Developing Modern Web Applications with ASP.NET Core and Microsoft Azure](https://aka.ms/WebAppEbook).
+- .NET Aspire App Hosting & Orchestration
+- An Blazor web application developed with ASP.NET Core.
+- A multi-platform app developed with .NET MAUI, which supports iOS, Android, macOS via Mac Catalyst, and Windows.
The sample application includes the following backend services:
@@ -73,9 +71,7 @@ The sample application includes the following backend services:
- An ordering microservice, which is a domain-driven service that uses domain-driven design patterns.
- A basket microservice, which is a data-driven CRUD service that uses Redis Cache.
-These backend services are implemented as microservices using ASP.NET Core MVC, and are deployed as unique containers within a single Docker host. Collectively, these backend services are referred to as the eShop reference application. Client apps communicate with the backend services through a Representational State Transfer (REST) web interface. For more information about microservices and Docker, see [Containerized microservices](micro-services.md).
-
-For information about the implementation of the backend services, see [.NET Microservices: Architecture for Containerized .NET Applications](https://aka.ms/microservicesebook).
+These backend services are implemented as microservices using ASP.NET Core, and are deployed as unique containers with .NET Aspire. Collectively, these backend services are referred to as the eShop reference application. Client apps communicate with the backend services through a Representational State Transfer (REST) web interface. For more information about microservices and conainers, see [Containerized microservices](micro-services.md).
## Multi-Platform app
@@ -99,7 +95,7 @@ The eShop multi-platform app exercises the following .NET MAUI functionality:
- Effects
- Custom Controls
-For more information about this functionality, see the [.NET MAUI documentation](/dotnet/maui) on the Microsoft Developer Center, and [Creating multi-platform apps with .NET MAUI](https://aka.ms/mauiebook).
+For more information about this functionality, see the [.NET MAUI documentation](/dotnet/maui).
In addition, unit tests are provided for some of the classes in the eShop multi-platform app.
diff --git a/docs/architecture/maui/media/high-level-architecture-diagram.png b/docs/architecture/maui/media/high-level-architecture-diagram.png
index 8bd32768251b7..5fd2dc26e107d 100644
Binary files a/docs/architecture/maui/media/high-level-architecture-diagram.png and b/docs/architecture/maui/media/high-level-architecture-diagram.png differ
diff --git a/docs/architecture/maui/media/mobile-authentication.png b/docs/architecture/maui/media/mobile-authentication.png
new file mode 100644
index 0000000000000..ab64d6836127e
Binary files /dev/null and b/docs/architecture/maui/media/mobile-authentication.png differ
diff --git a/docs/architecture/maui/micro-services.md b/docs/architecture/maui/micro-services.md
index c7f4592e29185..2e206024990d2 100644
--- a/docs/architecture/maui/micro-services.md
+++ b/docs/architecture/maui/micro-services.md
@@ -80,8 +80,6 @@ The architecture of the back-end services in the reference application is decomp
Each microservice has its own database, allowing it to be fully decoupled from the other microservices. Where necessary, consistency between databases from different microservices is achieved using application-level events. For more information, see [Communication between microservices](#communication-between-microservices).
-For more information about the reference application, see [.NET Microservices: Architecture for Containerized .NET Applications](https://aka.ms/microservicesebook).
-
## Communication between client and microservices
The eShop multi-platform app communicates with the containerized back-end microservices using _direct client-to-microservice_ communication, as shown below.
@@ -93,7 +91,7 @@ With direct client-to-microservice communication, the multi-platform app makes r
> [!TIP]
> Consider using API gateway communication.
-Direct client-to-microservice communication can have drawbacks when building a large and complex microservice-based application, but it's more than adequate for a small application. Consider using API gateway communication when designing a large microservice-based application with tens of microservices. For more information, see [.NET Microservices: Architecture for Containerized .NET Applications](https://aka.ms/microservicesebook).
+Direct client-to-microservice communication can have drawbacks when building a large and complex microservice-based application, but it's more than adequate for a small application. Consider using API gateway communication when designing a large microservice-based application with tens of microservices.
## Communication between microservices
@@ -117,11 +115,6 @@ The eShop event bus, implemented using RabbitMQ, provides one-to-many asynchrono
This one-to-many communication approach uses events to implement business transactions that span multiple services, ensuring eventual consistency between the services. An eventual-consistent transaction consists of a series of distributed steps. Therefore, when the user-profile microservice receives the UpdateUser command, it updates the user's details in its database and publishes the UserUpdated event to the event bus. Both the basket microservice and the ordering microservice have subscribed to receive this event, and in response, update their buyer information in their respective databases.
-> [!NOTE]
-> The eShop event bus, implemented using RabbitMQ, is intended to be used only as a proof of concept. For production systems, alternative event bus implementations should be considered.
-
-For more information about the event bus implementation, see [.NET Microservices: Architecture for Containerized .NET Applications](https://aka.ms/microservicesebook).
-
## Summary
Microservices offer an approach to application development and deployment that's suited to the agility, scale, and reliability requirements of modern cloud applications. One of the main advantages of microservices is that they can be scaled-out independently, which means that a specific functional area can be scaled that requires more processing power or network bandwidth to support demand without unnecessarily scaling areas of the application that are not experiencing increased demand.
diff --git a/docs/architecture/maui/mvvm.md b/docs/architecture/maui/mvvm.md
index 83d76dd79320d..4cef3f9163ab5 100644
--- a/docs/architecture/maui/mvvm.md
+++ b/docs/architecture/maui/mvvm.md
@@ -169,9 +169,9 @@ Using a lambda expression in this way involves a small performance cost because
## MVVM Frameworks
-The MVVM pattern is well established in .NET, and the community has created many frameworks which help ease this development. Each framework provides a different set of features, but it is standard for them to provide a common view model with an implementation of the `INotifyPropertyChanged` interface. Additional features of MVVM frameworks include custom commands, navigation helpers, dependency injection/service locator components, and UI platform integration. While it is not necessary to use these frameworks, they can speed up and standardize your development. The eShop multi-platform app uses [the .NET Community MVVM Toolkit](/windows/communitytoolkit/mvvm/introduction). When choosing a framework, you should consider your application's needs and your team's strengths. The list below includes some of the more common MVVM frameworks for .NET MAUI.
+The MVVM pattern is well established in .NET, and the community has created many frameworks which help ease this development. Each framework provides a different set of features, but it is standard for them to provide a common view model with an implementation of the `INotifyPropertyChanged` interface. Additional features of MVVM frameworks include custom commands, navigation helpers, dependency injection/service locator components, and UI platform integration. While it is not necessary to use these frameworks, they can speed up and standardize your development. The eShop multi-platform app uses [the .NET Community MVVM Toolkit](/dotnet/communitytoolkit/mvvm/introduction). When choosing a framework, you should consider your application's needs and your team's strengths. The list below includes some of the more common MVVM frameworks for .NET MAUI.
-- [.NET Community MVVM Toolkit](/windows/communitytoolkit/mvvm/introduction/)
+- [.NET Community MVVM Toolkit](/dotnet/communitytoolkit/mvvm/introduction/)
- [ReactiveUI](https://www.reactiveui.net/)
- [Prism Library](https://prismlibrary.com/)
@@ -199,7 +199,7 @@ Provided with .NET MAUI are the `Command` and `Command` classes that implemen
The `Command` or `Command` constructor requires an Action callback object that's called when the `ICommand.Execute` method is invoked. The `CanExecute` method is an optional constructor parameter, and is a Func that returns a bool.
-The eShop multi-platform app uses the [RelayCommand](/windows/communitytoolkit/mvvm/relaycommand) and [AsyncRelayCommand](/windows/communitytoolkit/mvvm/asyncrelaycommand). The primary benefit for modern applications is that the `AsyncRelayCommand` provides better functionality for asynchronous operations.
+The eShop multi-platform app uses the [RelayCommand](/dotnet/communitytoolkit/mvvm/relaycommand) and [AsyncRelayCommand](/dotnet/communitytoolkit/mvvm/asyncrelaycommand). The primary benefit for modern applications is that the `AsyncRelayCommand` provides better functionality for asynchronous operations.
The following code shows how a `Command` instance, which represents a register command, is constructed by specifying a delegate to the Register view model method:
diff --git a/docs/architecture/maui/preface.md b/docs/architecture/maui/preface.md
index 1400b5e8d5391..b207d59162014 100644
--- a/docs/architecture/maui/preface.md
+++ b/docs/architecture/maui/preface.md
@@ -10,7 +10,7 @@ ms.date: 05/30/2024
[!INCLUDE [download-alert](includes/download-alert.md)]
-This eBook provides guidance on building cross-platform enterprise apps using .NET MAUI. .NET MAUI is a cross-platform UI toolkit that allows developers to easily create native user interface layouts that can be shared across platforms, including iOS, macOS, Android, and Windows 10/11. It provides a comprehensive solution for Business to Employee (B2E), Business to Business (B2B), and Business to Consumer (B2C) apps, providing the ability to share code across all target platforms and helping to lower the total cost of ownership (TCO).
+This eBook provides guidance on building cross-platform enterprise apps using .NET MAUI. .NET MAUI is a cross-platform UI toolkit that allows developers to easily create native user interface layouts that can be shared across platforms, including iOS, macOS, Android, and Windows. It provides a comprehensive solution for Business to Employee (B2E), Business to Business (B2B), and Business to Consumer (B2C) apps, providing the ability to share code across all target platforms and helping to lower the total cost of ownership (TCO).
The guide provides architectural guidance for developing adaptable, maintainable, and testable .NET MAUI enterprise apps. Guidance is provided on how to implement MVVM, dependency injection, navigation, validation, and configuration management, while maintaining loose coupling. In addition, there's also guidance on performing authentication and authorization with IdentityServer, accessing data from containerized microservices, and unit testing.
@@ -18,9 +18,7 @@ The guide comes with source code for the [eShop multi-platform app](https://gith
## What's left out of this guide's scope
-This guide is aimed at readers who are already familiar with .NET MAUI. For a detailed introduction to .NET MAUI, see the [.NET MAUI documentation](/dotnet/maui/) on the Microsoft Developer Center, and [Creating multi-platform apps with .NET MAUI](https://aka.ms/mauiebook).
-
-The guide is complementary to [.NET Microservices: Architecture for Containerized .NET Applications](https://aka.ms/microservicesebook), which focuses on developing and deploying containerized microservices. Other guides worth reading include [Architecting and Developing Modern Web Applications with ASP.NET Core and Microsoft Azure](https://aka.ms/WebAppEbook), [Containerized Docker Application Lifecycle with Microsoft Platform and Tools](https://aka.ms/dockerlifecycleebook), and [Microsoft Platform and Tools for Mobile App Development](https://aka.ms/MobAppDev/StndPDF).
+This guide is aimed at readers who are already familiar with .NET MAUI. For a detailed introduction to .NET MAUI, see the [.NET MAUI documentation](/dotnet/maui/).
## Who should use this guide
diff --git a/docs/azure/includes/dotnet-all.md b/docs/azure/includes/dotnet-all.md
index 004c7c883e4ec..22fa14bb76a8a 100644
--- a/docs/azure/includes/dotnet-all.md
+++ b/docs/azure/includes/dotnet-all.md
@@ -176,7 +176,7 @@
| Resource Management - Container Service | NuGet [1.2.2](https://www.nuget.org/packages/Azure.ResourceManager.ContainerService/1.2.2) | [docs](/dotnet/api/overview/azure/ResourceManager.ContainerService-readme) | GitHub [1.2.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ContainerService_1.2.2/sdk/containerservice/Azure.ResourceManager.ContainerService/) |
| Resource Management - Container Service Fleet | NuGet [1.0.0](https://www.nuget.org/packages/Azure.ResourceManager.ContainerServiceFleet/1.0.0) | [docs](/dotnet/api/overview/azure/ResourceManager.ContainerServiceFleet-readme) | GitHub [1.0.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ContainerServiceFleet_1.0.0/sdk/fleet/Azure.ResourceManager.ContainerServiceFleet/) |
| Resource Management - Content Delivery Network | NuGet [1.3.0](https://www.nuget.org/packages/Azure.ResourceManager.Cdn/1.3.0) | [docs](/dotnet/api/overview/azure/ResourceManager.Cdn-readme) | GitHub [1.3.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Cdn_1.3.0/sdk/cdn/Azure.ResourceManager.Cdn/) |
-| Resource Management - Cosmos DB | NuGet [1.3.2](https://www.nuget.org/packages/Azure.ResourceManager.CosmosDB/1.3.2) NuGet [1.4.0-beta.9](https://www.nuget.org/packages/Azure.ResourceManager.CosmosDB/1.4.0-beta.9) | [docs](/dotnet/api/overview/azure/ResourceManager.CosmosDB-readme) | GitHub [1.3.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CosmosDB_1.3.2/sdk/cosmosdb/Azure.ResourceManager.CosmosDB/) GitHub [1.4.0-beta.9](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CosmosDB_1.4.0-beta.9/sdk/cosmosdb/Azure.ResourceManager.CosmosDB/) |
+| Resource Management - Cosmos DB | NuGet [1.3.2](https://www.nuget.org/packages/Azure.ResourceManager.CosmosDB/1.3.2) NuGet [1.4.0-beta.10](https://www.nuget.org/packages/Azure.ResourceManager.CosmosDB/1.4.0-beta.10) | [docs](/dotnet/api/overview/azure/ResourceManager.CosmosDB-readme) | GitHub [1.3.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CosmosDB_1.3.2/sdk/cosmosdb/Azure.ResourceManager.CosmosDB/) GitHub [1.4.0-beta.10](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CosmosDB_1.4.0-beta.10/sdk/cosmosdb/Azure.ResourceManager.CosmosDB/) |
| Resource Management - Cosmos DB for PostgreSQL | NuGet [1.0.0](https://www.nuget.org/packages/Azure.ResourceManager.CosmosDBForPostgreSql/1.0.0) NuGet [1.1.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.CosmosDBForPostgreSql/1.1.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.CosmosDBForPostgreSql-readme) | GitHub [1.0.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CosmosDBForPostgreSql_1.0.0/sdk/cosmosdbforpostgresql/Azure.ResourceManager.CosmosDBForPostgreSql/) GitHub [1.1.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CosmosDBForPostgreSql_1.1.0-beta.1/sdk/cosmosdbforpostgresql/Azure.ResourceManager.CosmosDBForPostgreSql/) |
| Resource Management - Costmanagement | NuGet [1.0.1](https://www.nuget.org/packages/Azure.ResourceManager.CostManagement/1.0.1) | [docs](/dotnet/api/overview/azure/ResourceManager.CostManagement-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CostManagement_1.0.1/sdk/costmanagement/Azure.ResourceManager.CostManagement/) |
| Resource Management - Customer Insights | NuGet [1.0.0-beta.4](https://www.nuget.org/packages/Azure.ResourceManager.CustomerInsights/1.0.0-beta.4) | [docs](/dotnet/api/overview/azure/ResourceManager.CustomerInsights-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CustomerInsights_1.0.0-beta.4/sdk/customer-insights/Azure.ResourceManager.CustomerInsights/) |
@@ -262,6 +262,7 @@
| Resource Management - New Relic Observability | NuGet [1.0.1](https://www.nuget.org/packages/Azure.ResourceManager.NewRelicObservability/1.0.1) | [docs](/dotnet/api/overview/azure/ResourceManager.NewRelicObservability-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.NewRelicObservability_1.0.1/sdk/newrelicobservability/Azure.ResourceManager.NewRelicObservability/) |
| Resource Management - Nginx | NuGet [1.0.0](https://www.nuget.org/packages/Azure.ResourceManager.Nginx/1.0.0) NuGet [1.1.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.Nginx/1.1.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.Nginx-readme) | GitHub [1.0.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Nginx_1.0.0/sdk/nginx/Azure.ResourceManager.Nginx/) GitHub [1.1.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Nginx_1.1.0-beta.1/sdk/nginx/Azure.ResourceManager.Nginx/) |
| Resource Management - Notification Hubs | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.NotificationHubs/1.1.0) NuGet [1.2.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.NotificationHubs/1.2.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.NotificationHubs-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.NotificationHubs_1.1.0/sdk/notificationhubs/Azure.ResourceManager.NotificationHubs/) GitHub [1.2.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.NotificationHubs_1.2.0-beta.1/sdk/notificationhubs/Azure.ResourceManager.NotificationHubs/) |
+| Resource Management - Oracledatabase | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.OracleDatabase/1.0.0-beta.1) | | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.OracleDatabase_1.0.0-beta.1/sdk/oracle/Azure.ResourceManager.OracleDatabase/) |
| Resource Management - Orbital | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.Orbital/1.1.0) | [docs](/dotnet/api/overview/azure/ResourceManager.Orbital-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Orbital_1.1.0/sdk/orbital/Azure.ResourceManager.Orbital/) |
| Resource Management - Palo Alto Networks - Next Generation Firewall | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.PaloAltoNetworks.Ngfw/1.1.0) | [docs](/dotnet/api/overview/azure/ResourceManager.PaloAltoNetworks.Ngfw-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.PaloAltoNetworks.Ngfw_1.1.0/sdk/paloaltonetworks.ngfw/Azure.ResourceManager.PaloAltoNetworks.Ngfw/) |
| Resource Management - Peering | NuGet [1.2.1](https://www.nuget.org/packages/Azure.ResourceManager.Peering/1.2.1) | [docs](/dotnet/api/overview/azure/ResourceManager.Peering-readme) | GitHub [1.2.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Peering_1.2.1/sdk/peering/Azure.ResourceManager.Peering/) |
@@ -294,10 +295,10 @@
| Resource Management - Security | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.SecurityCenter/1.1.0) NuGet [1.2.0-beta.5](https://www.nuget.org/packages/Azure.ResourceManager.SecurityCenter/1.2.0-beta.5) | [docs](/dotnet/api/overview/azure/ResourceManager.SecurityCenter-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SecurityCenter_1.1.0/sdk/securitycenter/Azure.ResourceManager.SecurityCenter/) GitHub [1.2.0-beta.5](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SecurityCenter_1.2.0-beta.5/sdk/securitycenter/Azure.ResourceManager.SecurityCenter/) |
| Resource Management - Security DevOps | NuGet [1.0.0-beta.4](https://www.nuget.org/packages/Azure.ResourceManager.SecurityDevOps/1.0.0-beta.4) | [docs](/dotnet/api/overview/azure/ResourceManager.SecurityDevOps-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SecurityDevOps_1.0.0-beta.4/sdk/securitydevops/Azure.ResourceManager.SecurityDevOps/) |
| Resource Management - Security Insights | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.SecurityInsights/1.1.0) | [docs](/dotnet/api/overview/azure/ResourceManager.SecurityInsights-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SecurityInsights_1.1.0/sdk/securityinsights/Azure.ResourceManager.SecurityInsights/) |
-| Resource Management - Self Help | NuGet [1.0.0](https://www.nuget.org/packages/Azure.ResourceManager.SelfHelp/1.0.0) NuGet [1.1.0-beta.3](https://www.nuget.org/packages/Azure.ResourceManager.SelfHelp/1.1.0-beta.3) | [docs](/dotnet/api/overview/azure/ResourceManager.SelfHelp-readme) | GitHub [1.0.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SelfHelp_1.0.0/sdk/selfhelp/Azure.ResourceManager.SelfHelp/) GitHub [1.1.0-beta.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SelfHelp_1.1.0-beta.3/sdk/selfhelp/Azure.ResourceManager.SelfHelp/) |
+| Resource Management - Self Help | NuGet [1.0.0](https://www.nuget.org/packages/Azure.ResourceManager.SelfHelp/1.0.0) NuGet [1.1.0-beta.4](https://www.nuget.org/packages/Azure.ResourceManager.SelfHelp/1.1.0-beta.4) | [docs](/dotnet/api/overview/azure/ResourceManager.SelfHelp-readme) | GitHub [1.0.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SelfHelp_1.0.0/sdk/selfhelp/Azure.ResourceManager.SelfHelp/) GitHub [1.1.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SelfHelp_1.1.0-beta.4/sdk/selfhelp/Azure.ResourceManager.SelfHelp/) |
| Resource Management - Service Bus | NuGet [1.0.1](https://www.nuget.org/packages/Azure.ResourceManager.ServiceBus/1.0.1) NuGet [1.1.0-beta.7](https://www.nuget.org/packages/Azure.ResourceManager.ServiceBus/1.1.0-beta.7) | [docs](/dotnet/api/overview/azure/ResourceManager.ServiceBus-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceBus_1.0.1/sdk/servicebus/Azure.ResourceManager.ServiceBus/) GitHub [1.1.0-beta.7](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceBus_1.1.0-beta.7/sdk/servicebus/Azure.ResourceManager.ServiceBus/) |
| Resource Management - Service Fabric | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.ServiceFabric/1.1.0) NuGet [1.2.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.ServiceFabric/1.2.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.ServiceFabric-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceFabric_1.1.0/sdk/servicefabric/Azure.ResourceManager.ServiceFabric/) GitHub [1.2.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceFabric_1.2.0-beta.1/sdk/servicefabric/Azure.ResourceManager.ServiceFabric/) |
-| Resource Management - Service Fabric Managed Clusters | NuGet [1.0.1](https://www.nuget.org/packages/Azure.ResourceManager.ServiceFabricManagedClusters/1.0.1) NuGet [1.1.0-beta.4](https://www.nuget.org/packages/Azure.ResourceManager.ServiceFabricManagedClusters/1.1.0-beta.4) | [docs](/dotnet/api/overview/azure/ResourceManager.ServiceFabricManagedClusters-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceFabricManagedClusters_1.0.1/sdk/servicefabricmanagedclusters/Azure.ResourceManager.ServiceFabricManagedClusters/) GitHub [1.1.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceFabricManagedClusters_1.1.0-beta.4/sdk/servicefabricmanagedclusters/Azure.ResourceManager.ServiceFabricManagedClusters/) |
+| Resource Management - Service Fabric Managed Clusters | NuGet [1.2.0](https://www.nuget.org/packages/Azure.ResourceManager.ServiceFabricManagedClusters/1.2.0) | [docs](/dotnet/api/overview/azure/ResourceManager.ServiceFabricManagedClusters-readme) | GitHub [1.2.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceFabricManagedClusters_1.2.0/sdk/servicefabricmanagedclusters/Azure.ResourceManager.ServiceFabricManagedClusters/) |
| Resource Management - Service Linker | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.ServiceLinker/1.1.0) | [docs](/dotnet/api/overview/azure/ResourceManager.ServiceLinker-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceLinker_1.1.0/sdk/servicelinker/Azure.ResourceManager.ServiceLinker/) |
| Resource Management - Service Networking | NuGet [1.0.1](https://www.nuget.org/packages/Azure.ResourceManager.ServiceNetworking/1.0.1) | [docs](/dotnet/api/overview/azure/ResourceManager.ServiceNetworking-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceNetworking_1.0.1/sdk/servicenetworking/Azure.ResourceManager.ServiceNetworking/) |
| Resource Management - SignalR | NuGet [1.1.2](https://www.nuget.org/packages/Azure.ResourceManager.SignalR/1.1.2) | [docs](/dotnet/api/overview/azure/ResourceManager.SignalR-readme) | GitHub [1.1.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SignalR_1.1.2/sdk/signalr/Azure.ResourceManager.SignalR/) |
@@ -309,7 +310,7 @@
| Resource Management - Storage | NuGet [1.2.3](https://www.nuget.org/packages/Azure.ResourceManager.Storage/1.2.3) | [docs](/dotnet/api/overview/azure/ResourceManager.Storage-readme) | GitHub [1.2.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Storage_1.2.3/sdk/storage/Azure.ResourceManager.Storage/) |
| Resource Management - Storage Actions | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.StorageActions/1.0.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.StorageActions-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StorageActions_1.0.0-beta.1/sdk/storageactions/Azure.ResourceManager.StorageActions/) |
| Resource Management - Storage Cache | NuGet [1.3.0](https://www.nuget.org/packages/Azure.ResourceManager.StorageCache/1.3.0) | [docs](/dotnet/api/overview/azure/ResourceManager.StorageCache-readme) | GitHub [1.3.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StorageCache_1.3.0/sdk/storagecache/Azure.ResourceManager.StorageCache/) |
-| Resource Management - Storage Mover | NuGet [1.1.1](https://www.nuget.org/packages/Azure.ResourceManager.StorageMover/1.1.1) | [docs](/dotnet/api/overview/azure/ResourceManager.StorageMover-readme) | GitHub [1.1.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StorageMover_1.1.1/sdk/storagemover/Azure.ResourceManager.StorageMover/) |
+| Resource Management - Storage Mover | NuGet [1.2.0](https://www.nuget.org/packages/Azure.ResourceManager.StorageMover/1.2.0) | [docs](/dotnet/api/overview/azure/ResourceManager.StorageMover-readme) | GitHub [1.2.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StorageMover_1.2.0/sdk/storagemover/Azure.ResourceManager.StorageMover/) |
| Resource Management - Storage Pool | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.StoragePool/1.1.0) | [docs](/dotnet/api/overview/azure/ResourceManager.StoragePool-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StoragePool_1.1.0/sdk/storagepool/Azure.ResourceManager.StoragePool/) |
| Resource Management - Storage Sync | NuGet [1.2.0](https://www.nuget.org/packages/Azure.ResourceManager.StorageSync/1.2.0) | [docs](/dotnet/api/overview/azure/ResourceManager.StorageSync-readme) | GitHub [1.2.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StorageSync_1.2.0/sdk/storagesync/Azure.ResourceManager.StorageSync/) |
| Resource Management - Stream Analytics | NuGet [1.2.0](https://www.nuget.org/packages/Azure.ResourceManager.StreamAnalytics/1.2.0) | [docs](/dotnet/api/overview/azure/ResourceManager.StreamAnalytics-readme) | GitHub [1.2.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StreamAnalytics_1.2.0/sdk/streamanalytics/Azure.ResourceManager.StreamAnalytics/) |
diff --git a/docs/azure/includes/dotnet-new.md b/docs/azure/includes/dotnet-new.md
index be639e916de1d..dd44fc9be24d5 100644
--- a/docs/azure/includes/dotnet-new.md
+++ b/docs/azure/includes/dotnet-new.md
@@ -181,7 +181,7 @@
| Resource Management - Container Service | NuGet [1.2.2](https://www.nuget.org/packages/Azure.ResourceManager.ContainerService/1.2.2) | [docs](/dotnet/api/overview/azure/ResourceManager.ContainerService-readme) | GitHub [1.2.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ContainerService_1.2.2/sdk/containerservice/Azure.ResourceManager.ContainerService/) |
| Resource Management - Container Service Fleet | NuGet [1.0.0](https://www.nuget.org/packages/Azure.ResourceManager.ContainerServiceFleet/1.0.0) | [docs](/dotnet/api/overview/azure/ResourceManager.ContainerServiceFleet-readme) | GitHub [1.0.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ContainerServiceFleet_1.0.0/sdk/fleet/Azure.ResourceManager.ContainerServiceFleet/) |
| Resource Management - Content Delivery Network | NuGet [1.3.0](https://www.nuget.org/packages/Azure.ResourceManager.Cdn/1.3.0) | [docs](/dotnet/api/overview/azure/ResourceManager.Cdn-readme) | GitHub [1.3.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Cdn_1.3.0/sdk/cdn/Azure.ResourceManager.Cdn/) |
-| Resource Management - Cosmos DB | NuGet [1.3.2](https://www.nuget.org/packages/Azure.ResourceManager.CosmosDB/1.3.2) NuGet [1.4.0-beta.9](https://www.nuget.org/packages/Azure.ResourceManager.CosmosDB/1.4.0-beta.9) | [docs](/dotnet/api/overview/azure/ResourceManager.CosmosDB-readme) | GitHub [1.3.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CosmosDB_1.3.2/sdk/cosmosdb/Azure.ResourceManager.CosmosDB/) GitHub [1.4.0-beta.9](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CosmosDB_1.4.0-beta.9/sdk/cosmosdb/Azure.ResourceManager.CosmosDB/) |
+| Resource Management - Cosmos DB | NuGet [1.3.2](https://www.nuget.org/packages/Azure.ResourceManager.CosmosDB/1.3.2) NuGet [1.4.0-beta.10](https://www.nuget.org/packages/Azure.ResourceManager.CosmosDB/1.4.0-beta.10) | [docs](/dotnet/api/overview/azure/ResourceManager.CosmosDB-readme) | GitHub [1.3.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CosmosDB_1.3.2/sdk/cosmosdb/Azure.ResourceManager.CosmosDB/) GitHub [1.4.0-beta.10](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CosmosDB_1.4.0-beta.10/sdk/cosmosdb/Azure.ResourceManager.CosmosDB/) |
| Resource Management - Cosmos DB for PostgreSQL | NuGet [1.0.0](https://www.nuget.org/packages/Azure.ResourceManager.CosmosDBForPostgreSql/1.0.0) NuGet [1.1.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.CosmosDBForPostgreSql/1.1.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.CosmosDBForPostgreSql-readme) | GitHub [1.0.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CosmosDBForPostgreSql_1.0.0/sdk/cosmosdbforpostgresql/Azure.ResourceManager.CosmosDBForPostgreSql/) GitHub [1.1.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CosmosDBForPostgreSql_1.1.0-beta.1/sdk/cosmosdbforpostgresql/Azure.ResourceManager.CosmosDBForPostgreSql/) |
| Resource Management - Costmanagement | NuGet [1.0.1](https://www.nuget.org/packages/Azure.ResourceManager.CostManagement/1.0.1) | [docs](/dotnet/api/overview/azure/ResourceManager.CostManagement-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CostManagement_1.0.1/sdk/costmanagement/Azure.ResourceManager.CostManagement/) |
| Resource Management - Customer Insights | NuGet [1.0.0-beta.4](https://www.nuget.org/packages/Azure.ResourceManager.CustomerInsights/1.0.0-beta.4) | [docs](/dotnet/api/overview/azure/ResourceManager.CustomerInsights-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.CustomerInsights_1.0.0-beta.4/sdk/customer-insights/Azure.ResourceManager.CustomerInsights/) |
@@ -268,6 +268,7 @@
| Resource Management - New Relic Observability | NuGet [1.0.1](https://www.nuget.org/packages/Azure.ResourceManager.NewRelicObservability/1.0.1) | [docs](/dotnet/api/overview/azure/ResourceManager.NewRelicObservability-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.NewRelicObservability_1.0.1/sdk/newrelicobservability/Azure.ResourceManager.NewRelicObservability/) |
| Resource Management - Nginx | NuGet [1.0.0](https://www.nuget.org/packages/Azure.ResourceManager.Nginx/1.0.0) NuGet [1.1.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.Nginx/1.1.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.Nginx-readme) | GitHub [1.0.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Nginx_1.0.0/sdk/nginx/Azure.ResourceManager.Nginx/) GitHub [1.1.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Nginx_1.1.0-beta.1/sdk/nginx/Azure.ResourceManager.Nginx/) |
| Resource Management - Notification Hubs | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.NotificationHubs/1.1.0) NuGet [1.2.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.NotificationHubs/1.2.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.NotificationHubs-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.NotificationHubs_1.1.0/sdk/notificationhubs/Azure.ResourceManager.NotificationHubs/) GitHub [1.2.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.NotificationHubs_1.2.0-beta.1/sdk/notificationhubs/Azure.ResourceManager.NotificationHubs/) |
+| Resource Management - Oracledatabase | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.OracleDatabase/1.0.0-beta.1) | | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.OracleDatabase_1.0.0-beta.1/sdk/oracle/Azure.ResourceManager.OracleDatabase/) |
| Resource Management - Orbital | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.Orbital/1.1.0) | [docs](/dotnet/api/overview/azure/ResourceManager.Orbital-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Orbital_1.1.0/sdk/orbital/Azure.ResourceManager.Orbital/) |
| Resource Management - Palo Alto Networks - Next Generation Firewall | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.PaloAltoNetworks.Ngfw/1.1.0) | [docs](/dotnet/api/overview/azure/ResourceManager.PaloAltoNetworks.Ngfw-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.PaloAltoNetworks.Ngfw_1.1.0/sdk/paloaltonetworks.ngfw/Azure.ResourceManager.PaloAltoNetworks.Ngfw/) |
| Resource Management - Peering | NuGet [1.2.1](https://www.nuget.org/packages/Azure.ResourceManager.Peering/1.2.1) | [docs](/dotnet/api/overview/azure/ResourceManager.Peering-readme) | GitHub [1.2.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Peering_1.2.1/sdk/peering/Azure.ResourceManager.Peering/) |
@@ -300,10 +301,10 @@
| Resource Management - Security | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.SecurityCenter/1.1.0) NuGet [1.2.0-beta.5](https://www.nuget.org/packages/Azure.ResourceManager.SecurityCenter/1.2.0-beta.5) | [docs](/dotnet/api/overview/azure/ResourceManager.SecurityCenter-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SecurityCenter_1.1.0/sdk/securitycenter/Azure.ResourceManager.SecurityCenter/) GitHub [1.2.0-beta.5](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SecurityCenter_1.2.0-beta.5/sdk/securitycenter/Azure.ResourceManager.SecurityCenter/) |
| Resource Management - Security DevOps | NuGet [1.0.0-beta.4](https://www.nuget.org/packages/Azure.ResourceManager.SecurityDevOps/1.0.0-beta.4) | [docs](/dotnet/api/overview/azure/ResourceManager.SecurityDevOps-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SecurityDevOps_1.0.0-beta.4/sdk/securitydevops/Azure.ResourceManager.SecurityDevOps/) |
| Resource Management - Security Insights | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.SecurityInsights/1.1.0) | [docs](/dotnet/api/overview/azure/ResourceManager.SecurityInsights-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SecurityInsights_1.1.0/sdk/securityinsights/Azure.ResourceManager.SecurityInsights/) |
-| Resource Management - Self Help | NuGet [1.0.0](https://www.nuget.org/packages/Azure.ResourceManager.SelfHelp/1.0.0) NuGet [1.1.0-beta.3](https://www.nuget.org/packages/Azure.ResourceManager.SelfHelp/1.1.0-beta.3) | [docs](/dotnet/api/overview/azure/ResourceManager.SelfHelp-readme) | GitHub [1.0.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SelfHelp_1.0.0/sdk/selfhelp/Azure.ResourceManager.SelfHelp/) GitHub [1.1.0-beta.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SelfHelp_1.1.0-beta.3/sdk/selfhelp/Azure.ResourceManager.SelfHelp/) |
+| Resource Management - Self Help | NuGet [1.0.0](https://www.nuget.org/packages/Azure.ResourceManager.SelfHelp/1.0.0) NuGet [1.1.0-beta.4](https://www.nuget.org/packages/Azure.ResourceManager.SelfHelp/1.1.0-beta.4) | [docs](/dotnet/api/overview/azure/ResourceManager.SelfHelp-readme) | GitHub [1.0.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SelfHelp_1.0.0/sdk/selfhelp/Azure.ResourceManager.SelfHelp/) GitHub [1.1.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SelfHelp_1.1.0-beta.4/sdk/selfhelp/Azure.ResourceManager.SelfHelp/) |
| Resource Management - Service Bus | NuGet [1.0.1](https://www.nuget.org/packages/Azure.ResourceManager.ServiceBus/1.0.1) NuGet [1.1.0-beta.7](https://www.nuget.org/packages/Azure.ResourceManager.ServiceBus/1.1.0-beta.7) | [docs](/dotnet/api/overview/azure/ResourceManager.ServiceBus-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceBus_1.0.1/sdk/servicebus/Azure.ResourceManager.ServiceBus/) GitHub [1.1.0-beta.7](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceBus_1.1.0-beta.7/sdk/servicebus/Azure.ResourceManager.ServiceBus/) |
| Resource Management - Service Fabric | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.ServiceFabric/1.1.0) NuGet [1.2.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.ServiceFabric/1.2.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.ServiceFabric-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceFabric_1.1.0/sdk/servicefabric/Azure.ResourceManager.ServiceFabric/) GitHub [1.2.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceFabric_1.2.0-beta.1/sdk/servicefabric/Azure.ResourceManager.ServiceFabric/) |
-| Resource Management - Service Fabric Managed Clusters | NuGet [1.0.1](https://www.nuget.org/packages/Azure.ResourceManager.ServiceFabricManagedClusters/1.0.1) NuGet [1.1.0-beta.4](https://www.nuget.org/packages/Azure.ResourceManager.ServiceFabricManagedClusters/1.1.0-beta.4) | [docs](/dotnet/api/overview/azure/ResourceManager.ServiceFabricManagedClusters-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceFabricManagedClusters_1.0.1/sdk/servicefabricmanagedclusters/Azure.ResourceManager.ServiceFabricManagedClusters/) GitHub [1.1.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceFabricManagedClusters_1.1.0-beta.4/sdk/servicefabricmanagedclusters/Azure.ResourceManager.ServiceFabricManagedClusters/) |
+| Resource Management - Service Fabric Managed Clusters | NuGet [1.2.0](https://www.nuget.org/packages/Azure.ResourceManager.ServiceFabricManagedClusters/1.2.0) | [docs](/dotnet/api/overview/azure/ResourceManager.ServiceFabricManagedClusters-readme) | GitHub [1.2.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceFabricManagedClusters_1.2.0/sdk/servicefabricmanagedclusters/Azure.ResourceManager.ServiceFabricManagedClusters/) |
| Resource Management - Service Linker | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.ServiceLinker/1.1.0) | [docs](/dotnet/api/overview/azure/ResourceManager.ServiceLinker-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceLinker_1.1.0/sdk/servicelinker/Azure.ResourceManager.ServiceLinker/) |
| Resource Management - Service Networking | NuGet [1.0.1](https://www.nuget.org/packages/Azure.ResourceManager.ServiceNetworking/1.0.1) | [docs](/dotnet/api/overview/azure/ResourceManager.ServiceNetworking-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.ServiceNetworking_1.0.1/sdk/servicenetworking/Azure.ResourceManager.ServiceNetworking/) |
| Resource Management - SignalR | NuGet [1.1.2](https://www.nuget.org/packages/Azure.ResourceManager.SignalR/1.1.2) | [docs](/dotnet/api/overview/azure/ResourceManager.SignalR-readme) | GitHub [1.1.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.SignalR_1.1.2/sdk/signalr/Azure.ResourceManager.SignalR/) |
@@ -315,7 +316,7 @@
| Resource Management - Storage | NuGet [1.2.3](https://www.nuget.org/packages/Azure.ResourceManager.Storage/1.2.3) | [docs](/dotnet/api/overview/azure/ResourceManager.Storage-readme) | GitHub [1.2.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Storage_1.2.3/sdk/storage/Azure.ResourceManager.Storage/) |
| Resource Management - Storage Actions | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.StorageActions/1.0.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.StorageActions-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StorageActions_1.0.0-beta.1/sdk/storageactions/Azure.ResourceManager.StorageActions/) |
| Resource Management - Storage Cache | NuGet [1.3.0](https://www.nuget.org/packages/Azure.ResourceManager.StorageCache/1.3.0) | [docs](/dotnet/api/overview/azure/ResourceManager.StorageCache-readme) | GitHub [1.3.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StorageCache_1.3.0/sdk/storagecache/Azure.ResourceManager.StorageCache/) |
-| Resource Management - Storage Mover | NuGet [1.1.1](https://www.nuget.org/packages/Azure.ResourceManager.StorageMover/1.1.1) | [docs](/dotnet/api/overview/azure/ResourceManager.StorageMover-readme) | GitHub [1.1.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StorageMover_1.1.1/sdk/storagemover/Azure.ResourceManager.StorageMover/) |
+| Resource Management - Storage Mover | NuGet [1.2.0](https://www.nuget.org/packages/Azure.ResourceManager.StorageMover/1.2.0) | [docs](/dotnet/api/overview/azure/ResourceManager.StorageMover-readme) | GitHub [1.2.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StorageMover_1.2.0/sdk/storagemover/Azure.ResourceManager.StorageMover/) |
| Resource Management - Storage Pool | NuGet [1.1.0](https://www.nuget.org/packages/Azure.ResourceManager.StoragePool/1.1.0) | [docs](/dotnet/api/overview/azure/ResourceManager.StoragePool-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StoragePool_1.1.0/sdk/storagepool/Azure.ResourceManager.StoragePool/) |
| Resource Management - Storage Sync | NuGet [1.2.0](https://www.nuget.org/packages/Azure.ResourceManager.StorageSync/1.2.0) | [docs](/dotnet/api/overview/azure/ResourceManager.StorageSync-readme) | GitHub [1.2.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StorageSync_1.2.0/sdk/storagesync/Azure.ResourceManager.StorageSync/) |
| Resource Management - Stream Analytics | NuGet [1.2.0](https://www.nuget.org/packages/Azure.ResourceManager.StreamAnalytics/1.2.0) | [docs](/dotnet/api/overview/azure/ResourceManager.StreamAnalytics-readme) | GitHub [1.2.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.StreamAnalytics_1.2.0/sdk/streamanalytics/Azure.ResourceManager.StreamAnalytics/) |
diff --git a/docs/azure/index.yml b/docs/azure/index.yml
index a48acab533f72..5a9c4be3a605d 100644
--- a/docs/azure/index.yml
+++ b/docs/azure/index.yml
@@ -8,7 +8,7 @@ metadata:
title: Azure for .NET developers
description: Samples, tutorials, and education for .NET on Azure
ms.topic: hub-page
- ms.service: azure-dotnet
+ ms.service: dotnet-azure
ms.date: 05/13/2021
highlightedContent:
diff --git a/docs/azure/landing-page.yml b/docs/azure/landing-page.yml
index f3c978a9fa1c0..befaccd3a458a 100644
--- a/docs/azure/landing-page.yml
+++ b/docs/azure/landing-page.yml
@@ -8,8 +8,7 @@ metadata:
ms.date: 06/12/2020
ms.topic: landing-page
ms.collection: collection
- ms.subservice: azure
- ms.service: azure-dotnet
+ ms.service: dotnet-azure
# ACOM
# https://azure.microsoft.com/develop/net/ .NET 🧡 Azure
diff --git a/docs/core/compatibility/9.0.md b/docs/core/compatibility/9.0.md
index 04b27f6a3f092..eeda53a177683 100644
--- a/docs/core/compatibility/9.0.md
+++ b/docs/core/compatibility/9.0.md
@@ -64,4 +64,4 @@ If you're migrating an app to .NET 9, the breaking changes listed here might aff
## See also
- [What's new in .NET 9](../whats-new/dotnet-9/overview.md)
-- [C# 13 breaking changes](../../../_roslyn/docs/compilers/CSharp/Compiler%20Breaking%20Changes%20-%20DotNet%209.md)
+- [C# 13 breaking changes](~/_roslyn/docs/compilers/CSharp/Compiler%20Breaking%20Changes%20-%20DotNet%209.md)
diff --git a/docs/core/compatibility/cryptography/5.0/default-cipher-suites-for-tls-on-linux.md b/docs/core/compatibility/cryptography/5.0/default-cipher-suites-for-tls-on-linux.md
index 4669b66c9eb01..2465d02dd2289 100644
--- a/docs/core/compatibility/cryptography/5.0/default-cipher-suites-for-tls-on-linux.md
+++ b/docs/core/compatibility/cryptography/5.0/default-cipher-suites-for-tls-on-linux.md
@@ -100,7 +100,7 @@ The new defaults are likely to work when communicating with modern clients or se
CipherString = ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256
```
-On the Red Hat Enterprise Linux, CentOS, and Fedora distributions, .NET applications default to the cipher suites permitted by the system-wide cryptographic policies. On these distributions, use the crypto-policies configuration instead of changing the OpenSSL configuration file.
+On the Red Hat Enterprise Linux, CentOS Stream, and Fedora distributions, .NET applications default to the cipher suites permitted by the system-wide cryptographic policies. On these distributions, use the crypto-policies configuration instead of changing the OpenSSL configuration file.
## Affected APIs
diff --git a/docs/core/extensions/logger-message-generator.md b/docs/core/extensions/logger-message-generator.md
index 8b881ddaeb1f8..e26a3e2c8e65f 100644
--- a/docs/core/extensions/logger-message-generator.md
+++ b/docs/core/extensions/logger-message-generator.md
@@ -1,7 +1,7 @@
---
title: Compile-time logging source generation
description: Learn how to use the LoggerMessageAttribute and compile-time source generation for logging in .NET.
-ms.date: 10/11/2023
+ms.date: 06/21/2024
---
# Compile-time logging source generation
@@ -60,6 +60,21 @@ public partial class InstanceLoggingExample
}
```
+Starting with .NET 9, the logging method can additionally get the logger from an `ILogger` primary constructor parameter in the containing class.
+
+```csharp
+public partial class InstanceLoggingExample(ILogger logger)
+{
+ [LoggerMessage(
+ EventId = 0,
+ Level = LogLevel.Critical,
+ Message = "Could not open socket to `{HostName}`")]
+ public partial void CouldNotOpenSocket(string hostName);
+}
+```
+
+If there is both an `ILogger` field and a primary constructor parameter, the logging method will get the logger from the field.
+
Sometimes, the log level needs to be dynamic rather than statically built into the code. You can do this by omitting the log level from the attribute and instead requiring it as a parameter to the logging method.
```csharp
diff --git a/docs/core/install/linux-centos.md b/docs/core/install/linux-centos.md
deleted file mode 100644
index b9fd55c5c9d60..0000000000000
--- a/docs/core/install/linux-centos.md
+++ /dev/null
@@ -1,103 +0,0 @@
----
-title: Install .NET on CentOS Linux
-description: Learn about which versions of .NET SDK and .NET Runtime are supported, and how to install .NET on CentOS Linux.
-author: adegeo
-ms.author: adegeo
-ms.date: 05/14/2024
-ms.custom: linux-related-content
----
-
-# Install the .NET SDK or the .NET Runtime on CentOS Linux
-
-.NET is supported on CentOS Linux. This article describes how to install .NET on CentOS Linux. If you need to install .NET On CentOS Stream, see [Install the .NET SDK or the .NET Runtime on RHEL and CentOS Stream](linux-rhel.md).
-
-[!INCLUDE [linux-intro-sdk-vs-runtime](includes/linux-intro-sdk-vs-runtime.md)]
-
-[!INCLUDE [linux-install-package-manager-x64-vs-arm](includes/linux-install-package-manager-x64-vs-arm.md)]
-
-## Supported distributions
-
-The following table is a list of currently supported .NET releases on CentOS Linux 7. These versions remain supported until either the version of [.NET reaches end-of-support](https://dotnet.microsoft.com/platform/support/policy/dotnet-core) or the version of CentOS Linux is no longer supported.
-
-| CentOS Linux | .NET |
-|--------------|------|
-| 7 | 6.0 |
-
-> [!WARNING]
-> CentOS Linux 8 reached an early End Of Life (EOL) on December 31st, 2021. For more information, see the official [CentOS Linux EOL page](https://www.centos.org/centos-linux-eol/). Because of this, .NET isn't supported on CentOS Linux 8.
-
-[!INCLUDE [versions-not-supported](includes/versions-not-supported.md)]
-
-[!INCLUDE [linux-install-package-manager-x64-vs-arm](includes/linux-install-package-manager-x64-vs-arm.md)]
-
-## Install preview versions
-
-[!INCLUDE [preview installs don't support package managers](./includes/linux-install-previews.md)]
-
-## Remove preview versions
-
-[!INCLUDE [package-manager uninstall notice](./includes/linux-uninstall-preview-info.md)]
-
-## CentOS Linux 7
-
-[!INCLUDE [linux-prep-intro-generic](includes/linux-prep-intro-generic.md)]
-
-```bash
-sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm
-```
-
-### Install the SDK
-
-The .NET SDK allows you to develop apps with .NET. If you install the .NET SDK, you don't need to install the corresponding runtime. To install the .NET SDK, run the following command:
-
-```bash
-sudo yum install dotnet-sdk-6.0
-```
-
-To learn how to use the .NET CLI, see [.NET CLI overview](../tools/index.md).
-
-### Install the runtime
-
-The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The following command installs the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your terminal, run the following command:
-
-```bash
-sudo yum install aspnetcore-runtime-6.0
-```
-
-As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET Core support: replace `aspnetcore-runtime-6.0` in the previous command with `dotnet-runtime-6.0`:
-
-```bash
-sudo yum install dotnet-runtime-6.0
-```
-
-To learn how to use the .NET CLI, see [.NET CLI overview](../tools/index.md).
-
-## How to install other versions
-
-[!INCLUDE [package-manager-switcher](./includes/package-manager-heading-hack-pkgname.md)]
-
-## Troubleshoot the package manager
-
-This section provides information on common errors you may get while using the package manager to install .NET.
-
-### Unable to find package
-
-[!INCLUDE [linux-install-package-manager-x64-vs-arm](includes/linux-install-package-manager-x64-vs-arm.md)]
-
-### Failed to fetch
-
-[!INCLUDE [package-manager-failed-to-fetch-rpm](includes/package-manager-failed-to-fetch-rpm.md)]
-
-### Errors related to missing `fxr`, `libhostfxr.so`, or `FrameworkList.xml`
-
-For more information about solving these problems, see [Troubleshoot `fxr`, `libhostfxr.so`, and `FrameworkList.xml` errors](linux-package-mixup.md).
-
-## Dependencies
-
-[!INCLUDE [linux-rpm-install-dependencies](includes/linux-rpm-install-dependencies.md)]
-
-## Next steps
-
-- [.NET CLI overview](../tools/index.md)
-- [How to enable TAB completion for the .NET CLI](../tools/enable-tab-autocomplete.md)
-- [Tutorial: Create a console application with .NET SDK using Visual Studio Code](../tutorials/with-visual-studio-code.md)
diff --git a/docs/core/install/linux-package-mixup.md b/docs/core/install/linux-package-mixup.md
index 1c2d2853599b0..abbe944472abf 100644
--- a/docs/core/install/linux-package-mixup.md
+++ b/docs/core/install/linux-package-mixup.md
@@ -44,7 +44,6 @@ These errors usually occur when two Linux package repositories provide .NET pack
- Alpine Linux
- Arch
-- CentOS
- CentOS Stream
- Fedora
- RHEL
diff --git a/docs/core/install/linux-rhel.md b/docs/core/install/linux-rhel.md
index f6a1016dfcb77..c2a57ca4c3ab8 100644
--- a/docs/core/install/linux-rhel.md
+++ b/docs/core/install/linux-rhel.md
@@ -28,11 +28,12 @@ The following table is a list of currently supported .NET releases on both RHEL
| Distribution | .NET |
| ---------------------- | --------- |
-| RHEL 9 (9.1) | 8.0, 6.0 |
-| RHEL 8 (8.7) | 8.0, 6.0 |
-| RHEL 7 | 6.0 |
-| CentOS Stream 9 | 8.0, 6.0 |
-| CentOS Stream 8 | 8.0, 6.0 |
+| [RHEL 9 (9.1)](#rhel-9) | 8.0, 6.0 |
+| [RHEL 8 (8.7)](#rhel-8) | 8.0, 6.0 |
+| [RHEL 7](#rhel-7--net-8) | 6.0 |
+| [CentOS Stream 9](#centos-stream-9) | 8.0, 6.0 |
+| [CentOS Stream 8](#centos-stream-8) | 8.0, 6.0 |
+| [CentOS Linux is no longer supported](#where-is-centos-linux) | |
[!INCLUDE [versions-not-supported](includes/versions-not-supported.md)]
@@ -108,13 +109,13 @@ source scl_source enable rh-dotnet60
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime that doesn't include ASP.NET Core support: replace `rh-dotnet60-aspnetcore-runtime-6.0` in the preceding command with `rh-dotnet60-dotnet-runtime-6.0`.
-## CentOS Stream 9 ✔️
+## CentOS Stream 9
.NET is included in the AppStream repositories for CentOS Stream 9.
[!INCLUDE [linux-dnf-install-80](includes/linux-install-80-dnf.md)]
-## CentOS Stream 8 ✔️
+## CentOS Stream 8
Use the Microsoft repository to install .NET:
@@ -125,6 +126,10 @@ sudo yum install dotnet-sdk-8.0
To learn how to use the .NET CLI, see [.NET CLI overview](../tools/index.md).
+## Where is CentOS Linux
+
+.NET is no longer supported on CentOS Linux. As of June 30th, 2024, CentOS Linux reached end-of-life. For more information, see [End dates are coming for CentOS Stream 8 and CentOS Linux 7](https://blog.centos.org/2023/04/end-dates-are-coming-for-centos-stream-8-and-centos-linux-7/).
+
## Dependencies
[!INCLUDE [linux-rpm-install-dependencies](includes/linux-rpm-install-dependencies.md)]
diff --git a/docs/core/install/linux-scripted-manual.md b/docs/core/install/linux-scripted-manual.md
index d44678facfb47..bf79f7227536e 100644
--- a/docs/core/install/linux-scripted-manual.md
+++ b/docs/core/install/linux-scripted-manual.md
@@ -36,7 +36,6 @@ It's possible that when you install .NET, specific dependencies may not be insta
- [Alpine](linux-alpine.md#dependencies)
- [Debian](linux-debian.md#dependencies)
-- [CentOS](linux-centos.md#dependencies)
- [Fedora](linux-fedora.md#dependencies)
- [RHEL and CentOS Stream](linux-rhel.md#dependencies)
- [SLES](linux-sles.md#dependencies)
diff --git a/docs/core/install/linux.md b/docs/core/install/linux.md
index d106a9829b929..81f5fa010cfb5 100644
--- a/docs/core/install/linux.md
+++ b/docs/core/install/linux.md
@@ -22,7 +22,6 @@ This article describes how .NET is available on various Linux distributions. .NE
.NET is available in [official package archives](https://github.com/dotnet/core/blob/main/linux.md) for various Linux distributions and [packages.microsoft.com](https://packages.microsoft.com/).
- [Alpine](linux-alpine.md)
-- [CentOS](linux-centos.md)
- [Debian](linux-debian.md)
- [Fedora](linux-fedora.md)
- [openSUSE](linux-opensuse.md)
diff --git a/docs/core/install/remove-runtime-sdk-versions.md b/docs/core/install/remove-runtime-sdk-versions.md
index d36464bc26024..b515b856e47dd 100644
--- a/docs/core/install/remove-runtime-sdk-versions.md
+++ b/docs/core/install/remove-runtime-sdk-versions.md
@@ -55,7 +55,7 @@ There's no need to first uninstall the .NET SDK when upgrading it using a packag
If you installed .NET using a package manager, use that same package manager to uninstall the .NET SDK or runtime. .NET installations support most popular package managers. Consult the documentation for your distribution's package manager for the precise syntax in your environment:
- [apt-get(8)](https://linux.die.net/man/8/apt-get) is used by Debian based systems, including Ubuntu.
-- [yum(8)](https://linux.die.net/man/8/yum) is used on Fedora, CentOS, Oracle Linux, and RHEL.
+- [yum(8)](https://linux.die.net/man/8/yum) is used on Fedora, CentOS Stream, Oracle Linux, and RHEL.
- [zypper(8)](https://en.opensuse.org/SDB:Zypper_manual_(plain)) is used on openSUSE and SUSE Linux Enterprise System (SLES).
- [dnf(8)](https://dnf.readthedocs.io/en/latest/command_ref.html) is used on Fedora.
diff --git a/docs/core/rid-catalog.md b/docs/core/rid-catalog.md
index dfe2ab1fa2762..d9c37f529cf17 100644
--- a/docs/core/rid-catalog.md
+++ b/docs/core/rid-catalog.md
@@ -110,7 +110,7 @@ For more information, see [Install .NET on Windows](install/windows.md#supported
### Linux RIDs
-- `linux-x64` (Most desktop distributions like CentOS, Debian, Fedora, Ubuntu, and derivatives)
+- `linux-x64` (Most desktop distributions like CentOS Stream, Debian, Fedora, Ubuntu, and derivatives)
- `linux-musl-x64` (Lightweight distributions using [musl](https://wiki.musl-libc.org/projects-using-musl.html) like Alpine Linux)
- `linux-musl-arm64` (Used to build Docker images for 64-bit Arm v8 and minimalistic base images)
- `linux-arm` (Linux distributions running on Arm like Raspbian on Raspberry Pi Model 2+)
diff --git a/docs/core/testing/unit-testing-platform-extensions-fakes.md b/docs/core/testing/unit-testing-platform-extensions-fakes.md
new file mode 100644
index 0000000000000..d702475bf0d63
--- /dev/null
+++ b/docs/core/testing/unit-testing-platform-extensions-fakes.md
@@ -0,0 +1,27 @@
+---
+title: Microsoft.Testing.Platform Fakes extension
+description: Learn about the various Microsoft.Testing.Platform Fakes extension capabilities and how to use it.
+author: drognanar
+ms.author: arturs
+ms.date: 06/21/2024
+---
+
+# Fakes extension
+
+The `Microsoft.Testing.Extensions.Fakes` extension provides support to execute a test project that makes use of `Microsoft Fakes`.
+
+[Microsoft Fakes](/visualstudio/test/isolating-code-under-test-with-microsoft-fakes) allows you to better test your code by either generating `Stub`s (for instance creating a testable implementation of `INotifyPropertyChanged`) or by `Shim`ing methods and static methods (replacing the implementation of `File.Open` with a one you can control in your tests).
+
+> [!NOTE]
+> This extension requires a Visual Studio Enterprise installation with the minimum version of 17.11 preview 1 in order to work correctly.
+
+## Upgrade your project to the new extension
+
+To use the new extension with an existing project, update the existing `Microsoft.QualityTools.Testing.Fakes` reference with `Microsoft.Testing.Extensions.Fakes`.
+
+```diff
+-
+- False
+-
++
+```
diff --git a/docs/core/testing/unit-testing-platform-extensions.md b/docs/core/testing/unit-testing-platform-extensions.md
index 922cdf50990f1..01dea3ee9bf41 100644
--- a/docs/core/testing/unit-testing-platform-extensions.md
+++ b/docs/core/testing/unit-testing-platform-extensions.md
@@ -37,3 +37,7 @@ Extensions allowing to produce test report files that contains information about
**[VSTest Bridge](./unit-testing-platform-extensions-vstest-bridge.md)**
This extension provides a compatibility layer with VSTest allowing the test frameworks depending on it to continue supporting running in VSTest mode (`vstest.console.exe`, usual `dotnet test`, `VSTest task` on AzDo, Test Explorers of Visual Studio and Visual Studio Code...).
+
+**[Microsoft Fakes](./unit-testing-platform-extensions-fakes.md)**
+
+This extension provides support to execute a test project that makes use of `Microsoft Fakes`.
diff --git a/docs/csharp/linq/snippets/HowToBuildDynamicQueries/HowToBuildDynamicQueries.csproj b/docs/csharp/linq/snippets/HowToBuildDynamicQueries/HowToBuildDynamicQueries.csproj
index 94b2d077ef19e..c2b0b8331982e 100644
--- a/docs/csharp/linq/snippets/HowToBuildDynamicQueries/HowToBuildDynamicQueries.csproj
+++ b/docs/csharp/linq/snippets/HowToBuildDynamicQueries/HowToBuildDynamicQueries.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst.Test/MakeConst.Test.csproj b/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst.Test/MakeConst.Test.csproj
index e65a3651f74f3..ff5f55f6deb2a 100644
--- a/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst.Test/MakeConst.Test.csproj
+++ b/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst.Test/MakeConst.Test.csproj
@@ -12,12 +12,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/docs/csharp/whats-new/csharp-13.md b/docs/csharp/whats-new/csharp-13.md
index 443a5283684ac..b980d17ec6107 100644
--- a/docs/csharp/whats-new/csharp-13.md
+++ b/docs/csharp/whats-new/csharp-13.md
@@ -20,6 +20,8 @@ You can download the latest .NET 9 preview SDK from the [.NET downloads page](ht
New features are added to the "What's new in C#" page when they're available in public preview releases. The [working set](https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md#working-set) section of the [roslyn feature status page](https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md) tracks when upcoming features are merged into the main branch.
+You can find any breaking changes introduced in C# 13 in our article on [breaking changes](~/_roslyn/docs/compilers/CSharp/Compiler%20Breaking%20Changes%20-%20DotNet%209.md).
+
[!INCLUDE [released-version-feedback](./includes/released-feedback.md)]
## `params` collections
diff --git a/docs/devops/dotnet-cli-and-continuous-integration.md b/docs/devops/dotnet-cli-and-continuous-integration.md
index 113f28b909754..da0dc7d19dad2 100644
--- a/docs/devops/dotnet-cli-and-continuous-integration.md
+++ b/docs/devops/dotnet-cli-and-continuous-integration.md
@@ -16,7 +16,7 @@ If you're using GitHub, the installation is straightforward. You can rely on Git
Native installers are available for macOS, Linux, and Windows. The installers require admin (sudo) access to the build server. The advantage of using a native installer is that it installs all of the native dependencies required for the tooling to run. Native installers also provide a system-wide installation of the SDK.
-macOS users should use the PKG installers. On Linux, there's a choice of using a feed-based package manager, such as apt-get for Ubuntu or yum for CentOS, or using the packages themselves, DEB or RPM. On Windows, use the MSI installer.
+macOS users should use the PKG installers. On Linux, there's a choice of using a feed-based package manager, such as apt-get for Ubuntu or yum for CentOS Stream, or using the packages themselves, DEB or RPM. On Windows, use the MSI installer.
The latest stable binaries are found at [.NET downloads](https://dotnet.microsoft.com/download). If you wish to use the latest (and potentially unstable) pre-release tooling, use the links provided at the [dotnet/installer GitHub repository](https://github.com/dotnet/installer#installers-and-binaries). For Linux distributions, `tar.gz` archives (also known as `tarballs`) are available; use the installation scripts within the archives to install .NET.
diff --git a/docs/fundamentals/syslib-diagnostics/source-generator-overview.md b/docs/fundamentals/syslib-diagnostics/source-generator-overview.md
index 13bcfb0e661c2..4478fd4dffa55 100644
--- a/docs/fundamentals/syslib-diagnostics/source-generator-overview.md
+++ b/docs/fundamentals/syslib-diagnostics/source-generator-overview.md
@@ -46,7 +46,7 @@ The following table provides an index to the `SYSLIB1XXX` diagnostics in .NET 6
| SYSLIB1024 | Logging method argument uses unsupported `out` parameter modifier |
| SYSLIB1025 | Multiple logging methods cannot use the same event name within a class |
| SYSLIB1026 | C# language version not supported by the logging source generator. |
-| SYSLIB1027 | (Reserved for logging.) |
+| SYSLIB1027 | Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field |
| SYSLIB1028 | (Reserved for logging.) |
| SYSLIB1029 | (Reserved for logging.) |
| [SYSLIB1030][1030] | The `System.Text.Json` source generator did not generate serialization metadata for type |
diff --git a/docs/orleans/grains/external-tasks-and-grains.md b/docs/orleans/grains/external-tasks-and-grains.md
index 1593beac0957a..7a3d53533a339 100644
--- a/docs/orleans/grains/external-tasks-and-grains.md
+++ b/docs/orleans/grains/external-tasks-and-grains.md
@@ -36,7 +36,7 @@ public async Task MyGrainMethod()
{
// Grab the grain's task scheduler
var orleansTS = TaskScheduler.Current;
- await TaskDelay(10_000);
+ await Task.Delay(10_000);
// Current task scheduler did not change, the code after await is still running
// in the same task scheduler.
diff --git a/docs/orleans/streaming/streams-programming-apis.md b/docs/orleans/streaming/streams-programming-apis.md
index 63a5a4cf9033c..96ce46a3392de 100644
--- a/docs/orleans/streaming/streams-programming-apis.md
+++ b/docs/orleans/streaming/streams-programming-apis.md
@@ -177,7 +177,7 @@ public override async Task OnActivateAsync(CancellationToken cancellationToken)
var streamId = StreamId.Create("MyStreamNamespace", this.GetPrimaryKey());
var stream = streamProvider.GetStream(streamId);
- await stream.SubscribeAsync(OnNextAsync)
+ await stream.SubscribeAsync(OnNextAsync);
}
```
@@ -195,7 +195,7 @@ public override async Task OnActivateAsync()
streamProvider.GetStream(
this.GetPrimaryKey(), "MyStreamNamespace");
- await stream.SubscribeAsync(OnNextAsync)
+ await stream.SubscribeAsync(OnNextAsync);
}
```
@@ -217,11 +217,10 @@ public async override Task OnActivateAsync(CancellationToken cancellationToken)
var stream = streamProvider.GetStream(streamId);
var subscriptionHandles = await stream.GetAllSubscriptionHandles();
- if (!subscriptionHandles.IsNullOrEmpty())
+ foreach (var handle in subscriptionHandles)
{
- subscriptionHandles.ForEach(
- async x => await x.ResumeAsync(OnNextAsync));
- }
+ await handle.ResumeAsync(this);
+ }
}
```