From eb87909b36dcacfbade37a1c3e3cb85d71f2e33d Mon Sep 17 00:00:00 2001 From: Alex Wiese Date: Wed, 16 Oct 2024 05:51:14 +1030 Subject: [PATCH 1/8] Fix typo NSWag => NSwag (#33852) --- aspnetcore/toc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/toc.yml b/aspnetcore/toc.yml index d5468f260068..36f7fe097d5f 100644 --- a/aspnetcore/toc.yml +++ b/aspnetcore/toc.yml @@ -862,7 +862,7 @@ items: uid: fundamentals/openapi/using-openapi-documents - name: OpenAPI tools uid: fundamentals/openapi/openapi-tools - - name: Swagger / NSWag + - name: Swagger / NSwag items: - name: Overview uid: tutorials/web-api-help-pages-using-swagger From 56a7a5ed1d03c1e88f1a594e438b8cd451b9215a Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Wed, 16 Oct 2024 07:50:28 -0400 Subject: [PATCH 2/8] Add cross-link to MAUI security article (#33855) --- aspnetcore/blazor/hybrid/tutorials/maui-blazor-web-app.md | 1 + 1 file changed, 1 insertion(+) diff --git a/aspnetcore/blazor/hybrid/tutorials/maui-blazor-web-app.md b/aspnetcore/blazor/hybrid/tutorials/maui-blazor-web-app.md index 324f6d490a05..73deab20dab6 100644 --- a/aspnetcore/blazor/hybrid/tutorials/maui-blazor-web-app.md +++ b/aspnetcore/blazor/hybrid/tutorials/maui-blazor-web-app.md @@ -784,5 +784,6 @@ You can also use compiler preprocessor directives in your RCL to implement diffe ## Additional resources +* * * From a9fa81d6bca2824839ed03c4b6391cfada697a2f Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:32:16 -0400 Subject: [PATCH 3/8] MapStaticAssets API cross-linking (#33856) --- aspnetcore/blazor/fundamentals/static-files.md | 16 ++++++++-------- .../webassembly/hosted-with-identity-server.md | 2 +- .../tutorials/movie-database-app/part-1.md | 2 +- aspnetcore/includes/IdentityServer4.md | 4 ++-- aspnetcore/migration/50-to-60.md | 2 +- aspnetcore/release-notes/aspnetcore-6.0.md | 4 ++-- .../security/identity-management-solutions.md | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/aspnetcore/blazor/fundamentals/static-files.md b/aspnetcore/blazor/fundamentals/static-files.md index 31bdb5e0eaf3..8e92dab03d16 100644 --- a/aspnetcore/blazor/fundamentals/static-files.md +++ b/aspnetcore/blazor/fundamentals/static-files.md @@ -24,10 +24,10 @@ Serving static assets is managed by either of the two middlewares described in t Middleware | API | .NET Version | Description --- | --- | :---: | --- -Map Static Assets | `MapStaticAssets` | .NET 9 or later | Optimizes the delivery of static assets to clients. -Static Files | | All .NET versions | Serves static assets to clients without the optimizations of `MapStaticAssets` but useful for some tasks that `MapStaticAssets` isn't capable of managing. +Map Static Assets | | .NET 9 or later | Optimizes the delivery of static assets to clients. +Static Files | | All .NET versions | Serves static assets to clients without the optimizations of Map Static Assets Middleware but useful for some tasks that Map Static Assets Middleware isn't capable of managing. -Configure Map Static Assets Middleware by calling `MapStaticAssets` in the app's request processing pipeline, which performs the following: +Configure Map Static Assets Middleware by calling in the app's request processing pipeline, which performs the following: * Sets the [ETag](https://developer.mozilla.org/docs/Web/HTTP/Headers/ETag) and [Last-Modified](https://developer.mozilla.org/docs/Web/HTTP/Headers/Last-Modified) headers. * Sets [caching headers](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cache-Control). @@ -36,13 +36,13 @@ Configure Map Static Assets Middleware by calling `MapStaticAssets` in the app's * Works with a [Content Delivery Network (CDN)](https://developer.mozilla.org/docs/Glossary/CDN) (for example, [Azure CDN](https://azure.microsoft.com/services/cdn/)) to serve the app's static assets closer to the user. * [Fingerprinting assets](https://developer.mozilla.org/docs/Glossary/Fingerprinting) to prevent reusing old versions of files. -`MapStaticAssets` operates by combining build and publish processes to collect information about the static assets in the app. This information is utilized by the runtime library to efficiently serve the static assets to browsers. +Map Static Assets Middleware operates by combining build and publish processes to collect information about the static assets in the app. This information is utilized by the runtime library to efficiently serve the static assets to browsers. -`MapStaticAssets` can replace in most situations. However, `MapStaticAssets` is optimized for serving the assets from known locations in the app at build and publish time. If the app serves assets from other locations, such as disk or embedded resources, should be used. +Map Static Assets Middleware can replace in most situations. However, Map Static Assets Middleware is optimized for serving the assets from known locations in the app at build and publish time. If the app serves assets from other locations, such as disk or embedded resources, should be used. -`MapStaticAssets` replaces calling in apps that serve Blazor WebAssembly framework files, and explicitly calling in a Blazor Web App isn't necessary because the API is automatically called when invoking . +Map Static Assets Middleware () replaces calling in apps that serve Blazor WebAssembly framework files, and explicitly calling in a Blazor Web App isn't necessary because the API is automatically called when invoking . -`MapStaticAssets` provides the following benefits that aren't available when calling : +Map Static Assets Middleware provides the following benefits that aren't available when calling : * Build-time compression for all the assets in the app, including JavaScript (JS) and stylesheets but excluding image and font assets that are already compressed. [Gzip](https://tools.ietf.org/html/rfc1952) (`Content-Encoding: gz`) compression is used during development. Gzip with [Brotli](https://tools.ietf.org/html/rfc7932) (`Content-Encoding: br`) compression is used during publish. * [Fingerprinting](https://developer.mozilla.org/docs/Glossary/Fingerprinting) for all assets at build time with a [Base64](https://developer.mozilla.org/docs/Glossary/Base64)-encoded string of the [SHA-256](xref:System.Security.Cryptography.SHA256) hash of each file's content. This prevents reusing an old version of a file, even if the old file is cached. Fingerprinted assets are cached using the [`immutable` directive](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cache-Control#directives), which results in the browser never requesting the asset again until it changes. For browsers that don't support the `immutable` directive, a [`max-age` directive](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cache-Control#directives) is added. @@ -63,7 +63,7 @@ When [Interactive WebAssembly or Interactive Auto render modes](xref:blazor/fund Map Static Assets Middleware doesn't provide features for minification or other file transformations. Minification is usually handled by custom code or [third-party tooling](xref:blazor/fundamentals/index#community-links-to-blazor-resources). -Static File Middleware () is useful in the following situations that `MapStaticAssets` can't handle: +Static File Middleware () is useful in the following situations that Map Static Assets Middleware () can't handle: * Applying a path prefix to Blazor WebAssembly static asset files, which is covered in the [Prefix for Blazor WebAssembly assets](#prefix-for-blazor-webassembly-assets) section. * Configuring file mappings of extensions to specific content types and setting static file options, which is covered in the [File mappings and static file options](#file-mappings-and-static-file-options) section. diff --git a/aspnetcore/blazor/security/webassembly/hosted-with-identity-server.md b/aspnetcore/blazor/security/webassembly/hosted-with-identity-server.md index c4bffba9f7f8..d5425f6fb4dc 100644 --- a/aspnetcore/blazor/security/webassembly/hosted-with-identity-server.md +++ b/aspnetcore/blazor/security/webassembly/hosted-with-identity-server.md @@ -611,7 +611,7 @@ The following guidance explains: * How to deploy a hosted Blazor WebAssembly app with Identity Server to [Azure App Service](https://azure.microsoft.com/services/app-service/) with a custom domain. * How to create and use a TLS certificate for HTTPS protocol communication with browsers. Although the guidance focuses on using the certificate with a custom domain, the guidance is equally applicable to using a default Azure Apps domain, for example `contoso.azurewebsites.net`. -For this hosting scenario, do **not** use the same certificate for [Identity Server's token signing key](https://docs.duendesoftware.com/identityserver/v5/fundamentals/keys/) and the site's HTTPS secure communication with browsers: +For this hosting scenario, do **not** use the same certificate for [Duende Identity Server's](https://docs.duendesoftware.com) token signing key and the site's HTTPS secure communication with browsers: * Using different certificates for these two requirements is a good security practice because it isolates private keys for each purpose. * TLS certificates for communication with browsers is managed independently without affecting Identity Server's token signing. diff --git a/aspnetcore/blazor/tutorials/movie-database-app/part-1.md b/aspnetcore/blazor/tutorials/movie-database-app/part-1.md index 332b85da5f53..f809bbbbf711 100644 --- a/aspnetcore/blazor/tutorials/movie-database-app/part-1.md +++ b/aspnetcore/blazor/tutorials/movie-database-app/part-1.md @@ -331,7 +331,7 @@ app.UseAntiforgery(); :::moniker range=">= aspnetcore-9.0" -Map Static Assets Middleware (`MapStaticAssets`) maps static files, such as images, scripts, and stylesheets, produced during the build as endpoints: +Map Static Assets Middleware () maps static files, such as images, scripts, and stylesheets, produced during the build as endpoints: ```csharp app.MapStaticAssets(); diff --git a/aspnetcore/includes/IdentityServer4.md b/aspnetcore/includes/IdentityServer4.md index 9756491e1ac0..fb41061ae6a3 100644 --- a/aspnetcore/includes/IdentityServer4.md +++ b/aspnetcore/includes/IdentityServer4.md @@ -2,7 +2,7 @@ ASP.NET Core Identity adds user interface (UI) login functionality to ASP.NET Co * [Microsoft Entra ID](/azure/api-management/api-management-howto-protect-backend-with-aad) * [Azure Active Directory B2C](/azure/active-directory-b2c/active-directory-b2c-custom-rest-api-netfw) (Azure AD B2C) -* [Duende IdentityServer](https://docs.duendesoftware.com/identityserver/v6/overview/). Duende IdentityServer is 3rd party product. +* [Duende IdentityServer](https://docs.duendesoftware.com). Duende IdentityServer is 3rd party product. Duende IdentityServer is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. Duende IdentityServer enables the following security features: @@ -11,6 +11,6 @@ Duende IdentityServer is an OpenID Connect and OAuth 2.0 framework for ASP.NET C * Access control for APIs * Federation Gateway -For more information, see [Overview of Duende IdentityServer](https://docs.duendesoftware.com/identityserver/v6/overview/). +For more information, see [Overview of Duende IdentityServer](https://docs.duendesoftware.com). For more information on other authentication providers, see [Community OSS authentication options for ASP.NET Core](xref:security/authentication/community) diff --git a/aspnetcore/migration/50-to-60.md b/aspnetcore/migration/50-to-60.md index 1e0c10668bb5..33cc62afe196 100644 --- a/aspnetcore/migration/50-to-60.md +++ b/aspnetcore/migration/50-to-60.md @@ -310,7 +310,7 @@ For more information, see [Razor compiler no longer produces a Views assembly](h ## Project templates use Duende Identity Server -Project templates now use [Duende Identity Server](https://docs.duendesoftware.com). For migration guidance, see [IdentityServer4 v4.1 to Duende IdentityServer v5](https://docs.duendesoftware.com/identityserver/v5/upgrades/is4_v4_to_dis_v5/). +Project templates now use [Duende Identity Server](https://docs.duendesoftware.com). > [!IMPORTANT] > Duende Identity Server is an open source product with a reciprocal license agreement. If you plan to use Duende Identity Server in production, you might be required to obtain a commercial licence from [Duende Software](https://duendesoftware.com/) and pay a license fee. For more information, see [Duende Software: Licenses](https://aka.ms/identityserverlicense). diff --git a/aspnetcore/release-notes/aspnetcore-6.0.md b/aspnetcore/release-notes/aspnetcore-6.0.md index 9574314a8f92..fd58ee567efc 100644 --- a/aspnetcore/release-notes/aspnetcore-6.0.md +++ b/aspnetcore/release-notes/aspnetcore-6.0.md @@ -387,9 +387,9 @@ See [Template generated ports for Kestrel](#tgp) in this document for more infor ### Authentication servers -.NET 3 to .NET 5 used [IdentityServer4](https://identityserver4.readthedocs.io) as part of our template to support the issuing of JWT tokens for SPA and Blazor applications. The templates now use the [Duende Identity Server](https://docs.duendesoftware.com/identityserver/v5). +.NET 3 to .NET 5 used [IdentityServer4](https://identityserver4.readthedocs.io) as part of our template to support the issuing of JWT tokens for SPA and Blazor applications. The templates now use the [Duende Identity Server](https://docs.duendesoftware.com). -If you are extending the identity models and are updating existing projects you need to update the namespaces in your code from `IdentityServer4.IdentityServer` to `Duende.IdentityServer` and follow their [migration instructions](https://docs.duendesoftware.com/identityserver/v5/upgrades/). +If you are extending the identity models and are updating existing projects, update the namespaces in your code from `IdentityServer4.IdentityServer` to `Duende.IdentityServer` and follow their migration instructions. The license model for Duende Identity Server has changed to a reciprocal license, which may require license fees when it's used commercially in production. See the [Duende license page](https://duendesoftware.com/products/identityserver#pricing) for more details. diff --git a/aspnetcore/security/identity-management-solutions.md b/aspnetcore/security/identity-management-solutions.md index 75f262322119..c1bfef6cc5f6 100644 --- a/aspnetcore/security/identity-management-solutions.md +++ b/aspnetcore/security/identity-management-solutions.md @@ -23,7 +23,7 @@ Many of the commercial licenses provide "community" or free options that may be |---------|-----|--------|---------|---------| |**ASP.NET Core Identity**| Self host |[OSS (MIT)](https://github.com/dotnet/aspnetcore/blob/main/LICENSE.txt)|[https://dotnet.microsoft.com/](https://dotnet.microsoft.com/apps/aspnet)|[Secure a web app with ASP.NET Core Identity](/training/modules/secure-aspnet-core-identity/)| |**Auth0**|Managed|[Commercial](https://auth0.com/pricing)|[https://auth0.com/](https://auth0.com/)|[Get started](https://auth0.com/docs/get-started)| -|**Duende IdentityServer**|Self host|[Commercial](https://duendesoftware.com/products/identityserver#pricing)|[https://duendesoftware.com/](https://duendesoftware.com/products/identityserver)|[ASP.NET Identity integration](https://docs.duendesoftware.com/identityserver/v6/aspnet_identity/)| +|**Duende IdentityServer**|Self host|[Commercial](https://duendesoftware.com/products/identityserver#pricing)|[https://duendesoftware.com/](https://duendesoftware.com/products/identityserver)|[ASP.NET Identity integration](https://docs.duendesoftware.com)| |**Keycloak**|Container|[OSS (Apache 2.0)](https://github.com/keycloak/keycloak/blob/master/LICENSE.txt)|[https://www.keycloak.org/](https://www.keycloak.org/)|[Keycloak documentation](https://www.keycloak.org/documentation)| |**Microsoft Entra ID**|Managed|[Commercial](https://azure.microsoft.com/pricing/details/active-directory/)|[https://azure.microsoft.com/services/active-directory/](https://azure.microsoft.com/services/active-directory/)|[Entra documentation](/azure/active-directory/fundamentals/active-directory-whatis)| |**Okta**|Managed|[Commercial](https://www.okta.com/pricing/)|[https://www.okta.com/](https://www.okta.com/)|[Okta for ASP.NET Core](https://developer.okta.com/code/dotnet/aspnetcore/)| @@ -34,7 +34,7 @@ Many of the commercial licenses provide "community" or free options that may be |---------|-----|--------|---------| |[ASP.NET Core Identity](https://dotnet.microsoft.com/apps/aspnet)| Self host |[OSS (MIT)](https://github.com/dotnet/aspnetcore/blob/main/LICENSE.txt)|[Secure a web app with ASP.NET Core Identity](/training/modules/secure-aspnet-core-identity/)| |[Auth0](https://auth0.com/)|Managed|[Commercial](https://auth0.com/pricing)|[Get started](https://auth0.com/docs/get-started)| -|[Duende IdentityServer](https://duendesoftware.com/products/identityserver)|Self host|[Commercial](https://duendesoftware.com/products/identityserver#pricing)|[ASP.NET Identity integration](https://docs.duendesoftware.com/identityserver/v6/aspnet_identity/)| +|[Duende IdentityServer](https://duendesoftware.com/products/identityserver)|Self host|[Commercial](https://duendesoftware.com/products/identityserver#pricing)|[ASP.NET Identity integration](https://docs.duendesoftware.com)| |[Keycloak](https://www.keycloak.org)|Container|[OSS (Apache 2.0)](https://github.com/keycloak/keycloak/blob/master/LICENSE.txt)|[Keycloak securing apps documentation](https://www.keycloak.org/guides#securing-apps)| |[Microsoft Entra ID](https://azure.microsoft.com/services/active-directory)|Managed|[Commercial](https://azure.microsoft.com/pricing/details/active-directory/)|[Entra documentation](/azure/active-directory/fundamentals/active-directory-whatis)| |[Okta](https://www.okta.com)|Managed|[Commercial](https://www.okta.com/pricing/)|[Okta for ASP.NET Core](https://developer.okta.com/code/dotnet/aspnetcore/)| From b6528cf86515c7d1e8f77cf37c1db0552738f6f4 Mon Sep 17 00:00:00 2001 From: boldswiftsmartfiberhank Date: Wed, 16 Oct 2024 20:14:07 +0200 Subject: [PATCH 4/8] validation point-in-time fix (#33844) --- aspnetcore/fundamentals/configuration/options.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/aspnetcore/fundamentals/configuration/options.md b/aspnetcore/fundamentals/configuration/options.md index 373e594d3da4..817f5af03d46 100644 --- a/aspnetcore/fundamentals/configuration/options.md +++ b/aspnetcore/fundamentals/configuration/options.md @@ -208,7 +208,11 @@ Options validation also supports , , or implementation is created. To run options validation eagerly, when the app starts, call in `Program.cs`: +Options validation runs the first time a `TOption` instance is created. That means, for instance, when first +access to [`IOptionsSnapshot.Value`](xref:Microsoft.Extensions.Options.IOptionsSnapshot%601) occurs in a request pipeline or when +[`IOptionsMonitor.Get(string)`](xref:Microsoft.Extensions.Options.OptionsMonitor`1.Get(System.String)) is called on settings present. After settings are reloaded, validation runs again. The ASP.NET Core runtime uses to cache the options instance once it is created. + +To run options validation eagerly, when the app starts, call in `Program.cs`: :::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsValidationSample/Snippets/Program.cs" id="snippet_ValidateOnStart" highlight="4"::: From 58225bd384808402582baae749f9cd5c68b300b1 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Thu, 17 Oct 2024 08:13:17 -0400 Subject: [PATCH 5/8] Cross-link main doc set Static Files article (#33868) --- aspnetcore/blazor/fundamentals/static-files.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/aspnetcore/blazor/fundamentals/static-files.md b/aspnetcore/blazor/fundamentals/static-files.md index 8e92dab03d16..6eab79935e3f 100644 --- a/aspnetcore/blazor/fundamentals/static-files.md +++ b/aspnetcore/blazor/fundamentals/static-files.md @@ -67,13 +67,8 @@ Static File Middleware (. ---> ## Consume assets with Map Static File Middleware From 3262acd90b0ca7570b14f894d2de14841f142b14 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Thu, 17 Oct 2024 09:39:49 -0400 Subject: [PATCH 6/8] Cross-link 9.0 sample code (#33870) --- .../blazor/components/built-in-components.md | 40 +++- .../cascading-values-and-parameters.md | 52 ++++- .../blazor/components/control-head-content.md | 8 +- aspnetcore/blazor/components/data-binding.md | 128 +++++++++-- .../blazor/components/dynamiccomponent.md | 126 +++++++++-- .../element-component-model-relationships.md | 18 +- .../blazor/components/event-handling.md | 100 ++++++++- .../blazor/components/generic-type-support.md | 142 ++++++++++++ aspnetcore/blazor/components/index.md | 206 ++++++++++++++++-- aspnetcore/blazor/components/layouts.md | 32 ++- aspnetcore/blazor/components/lifecycle.md | 84 ++++++- .../components/overwriting-parameters.md | 40 +++- aspnetcore/blazor/components/quickgrid.md | 10 + aspnetcore/blazor/components/rendering.md | 24 +- ...lat-attributes-and-arbitrary-parameters.md | 44 +++- .../components/synchronization-context.md | 26 ++- .../blazor/components/templated-components.md | 56 ++++- .../blazor/components/virtualization.md | 14 ++ 18 files changed, 1044 insertions(+), 106 deletions(-) diff --git a/aspnetcore/blazor/components/built-in-components.md b/aspnetcore/blazor/components/built-in-components.md index c89f777df874..63049bb7036a 100644 --- a/aspnetcore/blazor/components/built-in-components.md +++ b/aspnetcore/blazor/components/built-in-components.md @@ -14,7 +14,45 @@ uid: blazor/components/built-in-components The following built-in Razor components are provided by the Blazor framework. For information on non-security-related project template components, see . For information on security-related project template components, see the [Security node articles](xref:blazor/security/index). -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +* [`AntiforgeryToken`](xref:blazor/forms/index#antiforgery-support) +* [`AuthorizeView`](xref:blazor/security/index#authorizeview-component) +* [`CascadingValue`](xref:blazor/components/cascading-values-and-parameters#cascadingvalue-component) +* [`DataAnnotationsValidator`](xref:blazor/forms/validation#data-annotations-validator-component-and-custom-validation) +* [`DynamicComponent`](xref:blazor/components/dynamiccomponent) +* [`Editor`](xref:blazor/forms/binding#nest-and-bind-forms) +* [`EditForm`](xref:blazor/forms/binding#editformeditcontext-model) +* [`ErrorBoundary`](xref:blazor/fundamentals/handle-errors#error-boundaries) +* [`FocusOnNavigate`](xref:blazor/fundamentals/routing#focus-an-element-on-navigation) +* [`HeadContent`](xref:blazor/components/control-head-content) +* [`HeadOutlet`](xref:blazor/components/control-head-content) +* [`ImportMap`](xref:blazor/fundamentals/static-files#import-maps) +* [`InputCheckbox`](xref:blazor/forms/input-components) +* [`InputDate`](xref:blazor/forms/input-components) +* [`InputFile`](xref:blazor/file-uploads) +* [`InputNumber`](xref:blazor/forms/input-components) +* [`InputRadio`](xref:blazor/forms/input-components) +* [`InputRadioGroup`](xref:blazor/forms/input-components) +* [`InputSelect`](xref:blazor/forms/input-components) +* [`InputText`](xref:blazor/forms/input-components) +* [`InputTextArea`](xref:blazor/forms/input-components) +* [`LayoutView`](xref:blazor/components/layouts#apply-a-layout-to-arbitrary-content-layoutview-component) +* [`NavigationLock`](xref:blazor/fundamentals/routing#handleprevent-location-changes) +* [`NavLink`](xref:blazor/fundamentals/routing#navlink-component) +* [`PageTitle`](xref:blazor/components/control-head-content) +* [`Paginator`](xref:blazor/components/quickgrid#page-items-with-a-paginator-component) +* [`QuickGrid`](xref:blazor/components/quickgrid) +* [`Router`](xref:blazor/fundamentals/routing#route-templates) +* [`RouteView`](xref:blazor/fundamentals/routing#route-templates) +* [`SectionContent`](xref:blazor/components/sections) +* [`SectionOutlet`](xref:blazor/components/sections) +* [`ValidationSummary`](xref:blazor/forms/validation#validation-summary-and-validation-message-components) +* [`Virtualize`](xref:blazor/components/virtualization) + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" * [`AntiforgeryToken`](xref:blazor/forms/index#antiforgery-support) * [`AuthorizeView`](xref:blazor/security/index#authorizeview-component) diff --git a/aspnetcore/blazor/components/cascading-values-and-parameters.md b/aspnetcore/blazor/components/cascading-values-and-parameters.md index 9d635ae0f075..c07560c5b8c5 100644 --- a/aspnetcore/blazor/components/cascading-values-and-parameters.md +++ b/aspnetcore/blazor/components/cascading-values-and-parameters.md @@ -29,8 +29,22 @@ The following class is used in this section's examples. `Dalek.cs`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Dalek.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" + :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Dalek.cs"::: +:::moniker-end + +:::moniker range=">= aspnetcore-8.0" + The following registrations are made in the app's `Program` file with : * `Dalek` with a property value for `Units` is registered as a fixed cascading value. @@ -45,8 +59,22 @@ The following `Daleks` component displays the cascaded values. `Daleks.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Daleks.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Daleks.razor"::: +:::moniker-end + +:::moniker range=">= aspnetcore-8.0" + In the following example, `Dalek` is registered as a cascading value using [`CascadingValueSource`](xref:Microsoft.AspNetCore.Components.CascadingValueSource%601), where `` is the type. The `isFixed` flag indicates whether the value is fixed. If false, all recipients are subscribed for update notifications, which are issued by calling . Subscriptions create overhead and reduce performance, so set `isFixed` to `true` if the value doesn't change. ```csharp @@ -81,7 +109,13 @@ The following `ThemeInfo` C# class specifies the theme information. `ThemeInfo.cs`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/ThemeInfo.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/ThemeInfo.cs"::: @@ -115,7 +149,13 @@ The following [layout component](xref:blazor/components/layouts) specifies theme `MainLayout.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Layout/MainLayout.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Layout/MainLayout.razor"::: @@ -196,7 +236,13 @@ The following component binds the `ThemeInfo` cascading value to a cascading par `ThemedCounter.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/ThemedCounter.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/ThemedCounter.razor"::: diff --git a/aspnetcore/blazor/components/control-head-content.md b/aspnetcore/blazor/components/control-head-content.md index 33ad00529cdc..b032142f539b 100644 --- a/aspnetcore/blazor/components/control-head-content.md +++ b/aspnetcore/blazor/components/control-head-content.md @@ -24,7 +24,13 @@ The following example sets the page's title and description using Razor. `ControlHeadContent.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/ControlHeadContent.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/ControlHeadContent.razor"::: diff --git a/aspnetcore/blazor/components/data-binding.md b/aspnetcore/blazor/components/data-binding.md index 6cf2a9a0cdcc..0fed40610743 100644 --- a/aspnetcore/blazor/components/data-binding.md +++ b/aspnetcore/blazor/components/data-binding.md @@ -27,7 +27,13 @@ When an `` element loses focus, its bound field or property is updated. `Bind.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Bind.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Bind.razor"::: @@ -63,7 +69,13 @@ As a demonstration of how data binding composes in HTML, the following example b `BindTheory.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/BindTheory.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/BindTheory.razor"::: @@ -99,7 +111,13 @@ Bind a property or field on other DOM events by including an `@bind:event="{EVEN `Page/BindEvent.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/BindEvent.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/BindEvent.razor"::: @@ -321,7 +339,13 @@ Using `@bind:get`/`@bind:set` modifiers both controls the underlying value of `i `DecimalBinding.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/DecimalBinding.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/DecimalBinding.razor"::: @@ -452,7 +476,13 @@ Consider the following component, where an `` element is bound to an `int `UnparsableValues.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/UnparsableValues.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/UnparsableValues.razor"::: @@ -498,7 +528,13 @@ Data binding works with a single format string using `@bi `DateBinding.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/DateBinding.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/DateBinding.razor"::: @@ -559,7 +595,13 @@ The following `ChildBind` component has a `Year` component parameter and an ) can be pa `ComponentMetadata.cs`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/ComponentMetadata.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/ComponentMetadata.cs"::: @@ -236,7 +286,13 @@ Implement an event callback parameter ( for the parent callback method, `ShowDTMessage`. Note that the [`this` keyword](/dotnet/csharp/language-reference/keywords/this) isn't supported in C# field initialization, so a C# property is used for the parameter dictionary. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`DynamicComponent3.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/DynamicComponent3.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `DynamicComponent3.razor`: @@ -357,7 +439,13 @@ Create an interface to describe the dynamically-created component instance with `Interfaces/ILoggable.cs`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Interfaces/ILoggable.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Interfaces/ILoggable.cs"::: @@ -379,7 +467,13 @@ Each component definition implements the interface. The following example is a m `RocketLab3.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/RocketLab3.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/RocketLab3.razor"::: @@ -441,7 +535,13 @@ The parent component casts the dynamically-loaded component instance as an `ILog } ``` -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +For a working demonstration of the preceding example, see the [`DynamicComponent4` component in the Blazor sample app](https://github.com/dotnet/blazor-samples/blob/main/9.0/BlazorSample_BlazorWebApp/Components/Pages/DynamicComponent4.razor). + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" For a working demonstration of the preceding example, see the [`DynamicComponent4` component in the Blazor sample app](https://github.com/dotnet/blazor-samples/blob/main/8.0/BlazorSample_BlazorWebApp/Components/Pages/DynamicComponent4.razor). diff --git a/aspnetcore/blazor/components/element-component-model-relationships.md b/aspnetcore/blazor/components/element-component-model-relationships.md index 6d378f52c07b..2bd98948b749 100644 --- a/aspnetcore/blazor/components/element-component-model-relationships.md +++ b/aspnetcore/blazor/components/element-component-model-relationships.md @@ -32,7 +32,13 @@ This demonstration allows you to: `Details.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Details.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Details.razor"::: @@ -64,7 +70,15 @@ This demonstration allows you to: In the following parent component, each iteration of adding a person in `OnTimerCallback` results in Blazor rebuilding the entire collection. The page's focus remains on the *same index* position of `` elements, so the focus shifts each time a person is added. *Shifting the focus away from what the user selected isn't desirable behavior.* After demonstrating the poor behavior with the following component, the [`@key`](xref:mvc/views/razor#key) directive attribute is used to improve the user's experience. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`People.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/People.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `People.razor`: diff --git a/aspnetcore/blazor/components/event-handling.md b/aspnetcore/blazor/components/event-handling.md index e38c640f47f7..a38b975f0fca 100644 --- a/aspnetcore/blazor/components/event-handling.md +++ b/aspnetcore/blazor/components/event-handling.md @@ -45,7 +45,15 @@ The following code: * Calls the `UpdateHeading` method when the button is selected in the UI. * Calls the `CheckChanged` method when the checkbox is changed in the UI. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`EventHandler1.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/EventHandler1.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `EventHandler1.razor`: @@ -90,7 +98,15 @@ In the following example, `UpdateHeading`: * Is called asynchronously when the button is selected. * Waits two seconds before updating the heading. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`EventHandler2.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/EventHandler2.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `EventHandler2.razor`: @@ -134,7 +150,15 @@ In the following example, `UpdateHeading`: For events that support an event argument type, specifying an event parameter in the event method definition is only necessary if the event type is used in the method. In the following example, is used in the `ReportPointerLocation` method to set message text that reports the mouse coordinates when the user selects a button in the UI. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`EventHandler3.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/EventHandler3.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `EventHandler3.razor`: @@ -452,7 +476,15 @@ In a Razor component, attach the custom handler to an element. [Lambda expressions](/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions) are supported as the delegate event handler. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`EventHandler4.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/EventHandler4.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `EventHandler4.razor`: @@ -497,7 +529,15 @@ It's often convenient to close over additional values using C# method parameters * An event argument () in `e`. * The button number in `buttonNumber`. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`EventHandler5.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/EventHandler5.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `EventHandler5.razor`: @@ -565,7 +605,13 @@ The following `Child` component demonstrates how a button's `onclick` handler is `Child.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Child.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Child.razor"::: @@ -595,9 +641,17 @@ The following `Child` component demonstrates how a button's `onclick` handler is :::moniker-end -The `Parent` component sets the child's (`OnClickCallback`) to its `ShowMessage` method. +The parent component sets the child's (`OnClickCallback`) to its `ShowMessage` method. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`ParentChild.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/ParentChild.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `ParentChild.razor`: @@ -710,7 +764,15 @@ Use the [`@on{DOM EVENT}:preventDefault`](xref:mvc/views/razor#oneventpreventdef When a key is selected on an input device and the element focus is on a text box, a browser normally displays the key's character in the text box. In the following example, the default behavior is prevented by specifying the `@onkeydown:preventDefault` directive attribute. When the focus is on the `` element, the counter increments with the key sequence Shift++. The `+` character isn't assigned to the `` element's value. For more information on `keydown`, see [`MDN Web Docs: Document: keydown` event](https://developer.mozilla.org/docs/Web/API/Document/keydown_event). -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`EventHandler6.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/EventHandler6.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `EventHandler6.razor`: @@ -775,7 +837,15 @@ The `stopPropagation` directive attribute's effect is limited to the Blazor scop In the following example, selecting the checkbox prevents click events from the second child `
` from propagating to the parent `
`. Since propagated click events normally fire the `OnSelectParentDiv` method, selecting the second child `
` results in the parent `
` message appearing unless the checkbox is selected. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`EventHandler7.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/EventHandler7.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `EventHandler7.razor`: @@ -823,7 +893,15 @@ Call . For an example of generic typing with templated components, see . :::moniker range=">= aspnetcore-6.0" @@ -76,8 +96,22 @@ The following subsections provide examples of the preceding approaches using the `ListDisplay1.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/ListDisplay1.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-6.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/ListDisplay1.razor"::: +:::moniker-end + +:::moniker range=">= aspnetcore-6.0" + ### Explicit generic types based on ancestor components The demonstration in this section cascades a type explicitly for `TExample`. @@ -89,30 +123,100 @@ The following `ListItems2` component receives data and cascades a generic type p `ListItems2.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/ListItems2.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-6.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/ListItems2.razor"::: +:::moniker-end + +:::moniker range=">= aspnetcore-6.0" + The following parent component sets the child content () of two `ListItems2` components specifying the `ListItems2` types (`TExample`), which are cascaded to child components. `ListDisplay1` components are rendered with the list item data shown in the example. String data is used with the first `ListItems2` component, and integer data is used with the second `ListItems2` component. `Generics2.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Generics2.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-6.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Generics2.razor"::: +:::moniker-end + +:::moniker range=">= aspnetcore-6.0" + Specifying the type explicitly also allows the use of [cascading values and parameters](xref:blazor/components/cascading-values-and-parameters) to provide data to child components, as the following demonstration shows. `ListDisplay2.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/ListDisplay2.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-6.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/ListDisplay2.razor"::: +:::moniker-end + +:::moniker range=">= aspnetcore-6.0" + `ListItems3.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/ListItems3.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-6.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/ListItems3.razor"::: +:::moniker-end + +:::moniker range=">= aspnetcore-6.0" + When cascading the data in the following example, the type must be provided to the component. `Generics3.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Generics3.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-6.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Generics3.razor"::: +:::moniker-end + +:::moniker range=">= aspnetcore-6.0" + When multiple generic types are cascaded, values for all generic types in the set must be passed. In the following example, `TItem`, `TValue`, and `TEdit` are `GridColumn` generic types, but the parent component that places `GridColumn` doesn't specify the `TItem` type: ```razor @@ -134,18 +238,56 @@ The demonstration in this section cascades a type inferred for `TExample`. `ListItems4.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/ListItems4.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-6.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/ListItems4.razor"::: +:::moniker-end + +:::moniker range=">= aspnetcore-6.0" + The following component with inferred cascaded types provides different data for display. `Generics4.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Generics4.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-6.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Generics4.razor"::: +:::moniker-end + +:::moniker range=">= aspnetcore-6.0" + The following component with inferred cascaded types provides the same data for display. The following example directly assigns the data to the components. `Generics5.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Generics5.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-6.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Generics5.razor"::: :::moniker-end diff --git a/aspnetcore/blazor/components/index.md b/aspnetcore/blazor/components/index.md index 701657dc5f9c..941c744b040f 100644 --- a/aspnetcore/blazor/components/index.md +++ b/aspnetcore/blazor/components/index.md @@ -239,7 +239,13 @@ The following example shows the default `Counter` component with an [`@code`][1] `Counter.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Counter.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Counter.razor"::: @@ -273,7 +279,13 @@ The following `Counter` component splits presentation HTML and Razor markup from `CounterPartialClass.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CounterPartialClass.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/CounterPartialClass.razor"::: @@ -305,7 +317,13 @@ The following `Counter` component splits presentation HTML and Razor markup from `CounterPartialClass.razor.cs`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CounterPartialClass.razor.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/CounterPartialClass.razor.cs"::: @@ -433,7 +451,13 @@ In the following example, the `BlazorRocksBase1` base class derives from type to add a block of static HTML content to the rendered output of a component. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`MarkupStrings.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/MarkupStrings.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `MarkupStrings.razor`: @@ -1459,7 +1615,13 @@ The following example illustrates how to specify is called. The following example appears in the article and demonstrates the use of a lambda expression for the disposal of a . -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`TimerDisposal1.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/TimerDisposal1.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `TimerDisposal1.razor`: @@ -679,7 +729,15 @@ If a single object requires disposal, a lambda can be used to dispose of the obj If the object is created in a lifecycle method, such as [`OnInitialized{Async}`](#component-initialization-oninitializedasync), check for `null` before calling `Dispose`. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`TimerDisposal2.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/TimerDisposal2.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `TimerDisposal2.razor`: @@ -913,7 +971,13 @@ In the following example: `BackgroundWork.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/BackgroundWork.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/BackgroundWork.razor"::: diff --git a/aspnetcore/blazor/components/overwriting-parameters.md b/aspnetcore/blazor/components/overwriting-parameters.md index 88f77c97cc5c..c23ffb720d3a 100644 --- a/aspnetcore/blazor/components/overwriting-parameters.md +++ b/aspnetcore/blazor/components/overwriting-parameters.md @@ -44,7 +44,13 @@ After the following `ShowMoreExpander` component demonstrates an overwritten par `ShowMoreExpander.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/BadShowMoreExpander.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/BadShowMoreExpander.razor"::: @@ -81,7 +87,13 @@ The `ShowMoreExpander` component is added to the following `Expanders` parent co `Expanders.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Expanders.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Expanders.razor"::: @@ -136,7 +148,13 @@ The following revised `ShowMoreExpander` component: `ShowMoreExpander.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/ShowMoreExpander.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/ShowMoreExpander.razor"::: @@ -176,7 +194,13 @@ Consider following `ToggleExpander` component that: `ToggleExpander.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/ToggleExpander.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/ToggleExpander.razor"::: @@ -210,7 +234,13 @@ The `ToggleExpander` component should be used with the `@bind-Expanded="{field}" `ExpandersToggle.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/ExpandersToggle.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/ExpandersToggle.razor"::: diff --git a/aspnetcore/blazor/components/quickgrid.md b/aspnetcore/blazor/components/quickgrid.md index ef765437a7f7..4db05296429e 100644 --- a/aspnetcore/blazor/components/quickgrid.md +++ b/aspnetcore/blazor/components/quickgrid.md @@ -87,8 +87,18 @@ For Blazor Web Apps, the `QuickGrid` component must adopt an [interactive render `PromotionGrid.razor`: +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/PromotionGrid.razor"::: + +:::moniker-end + +:::moniker range="< aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/PromotionGrid.razor"::: +:::moniker-end + Access the component in a browser at the relative path `/promotion-grid`. There aren't current plans to extend `QuickGrid` with features that full-blown commercial grids tend to offer, for example, hierarchical rows, drag-to-reorder columns, or Excel-like range selections. If you require advanced features that you don't wish to develop on your own, continue using third-party grids. diff --git a/aspnetcore/blazor/components/rendering.md b/aspnetcore/blazor/components/rendering.md index afda9cc6c1f0..a49a24011414 100644 --- a/aspnetcore/blazor/components/rendering.md +++ b/aspnetcore/blazor/components/rendering.md @@ -111,7 +111,13 @@ Even if is `ControlRender.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/ControlRender.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/ControlRender.razor"::: @@ -208,7 +214,13 @@ Consider the following `CounterState1` component, which updates the count four t `CounterState1.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CounterState1.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/CounterState1.razor"::: @@ -253,7 +265,13 @@ Because the callback is invoked outside of Blazor's synchronization context, the `CounterState2.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CounterState2.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/CounterState2.razor"::: diff --git a/aspnetcore/blazor/components/splat-attributes-and-arbitrary-parameters.md b/aspnetcore/blazor/components/splat-attributes-and-arbitrary-parameters.md index 77de84ed2df2..ddd674746798 100644 --- a/aspnetcore/blazor/components/splat-attributes-and-arbitrary-parameters.md +++ b/aspnetcore/blazor/components/splat-attributes-and-arbitrary-parameters.md @@ -23,7 +23,13 @@ In the following `Splat` component: `Splat.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Splat.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Splat.razor"::: @@ -86,7 +92,13 @@ The position of [`@attributes`](xref:mvc/views/razor#attributes) relative to the `AttributeOrderChild1.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/AttributeOrderChild1.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/AttributeOrderChild1.razor"::: @@ -116,7 +128,15 @@ The position of [`@attributes`](xref:mvc/views/razor#attributes) relative to the :::moniker-end -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`AttributeOrder1.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/AttributeOrder1.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `AttributeOrder1.razor`: @@ -166,7 +186,13 @@ In the following example, the order of `extra` and [`@attributes`](xref:mvc/view `AttributeOrderChild2.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/AttributeOrderChild2.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/AttributeOrderChild2.razor"::: @@ -196,7 +222,15 @@ In the following example, the order of `extra` and [`@attributes`](xref:mvc/view :::moniker-end -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`AttributeOrder2.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/AttributeOrder2.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `AttributeOrder2.razor`: diff --git a/aspnetcore/blazor/components/synchronization-context.md b/aspnetcore/blazor/components/synchronization-context.md index 0350814c566e..47d769af89a6 100644 --- a/aspnetcore/blazor/components/synchronization-context.md +++ b/aspnetcore/blazor/components/synchronization-context.md @@ -36,7 +36,13 @@ In the event a component must be updated based on an external event, such as a t `TimerService.cs`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/TimerService.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/TimerService.cs"::: @@ -68,7 +74,13 @@ In the event a component must be updated based on an external event, such as a t `NotifierService.cs`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/NotifierService.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/NotifierService.cs"::: @@ -116,7 +128,15 @@ Register the services: Use the `NotifierService` to update a component. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`Notifications.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Notifications.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `Notifications.razor`: diff --git a/aspnetcore/blazor/components/templated-components.md b/aspnetcore/blazor/components/templated-components.md index 7c641c2186be..500831a4a497 100644 --- a/aspnetcore/blazor/components/templated-components.md +++ b/aspnetcore/blazor/components/templated-components.md @@ -33,7 +33,13 @@ Often, templated components are generically typed, as the following `TemplatedNa `TemplatedNavBar.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/TemplatedNavBar.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/TemplatedNavBar.razor"::: @@ -69,7 +75,13 @@ Specify the `Context` attribute on the component element when you want to specif `Pets1.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Pets1.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Pets1.razor"::: @@ -103,7 +115,13 @@ Alternatively, you can change the parameter name using the `Context` attribute o `Pets2.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Pets2.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Pets2.razor"::: @@ -137,7 +155,13 @@ Component arguments of type Date: Thu, 17 Oct 2024 14:57:09 -0400 Subject: [PATCH 7/8] MAUI Blazor Hybrid + BWA article 9.0 updates (#33865) --- .../hybrid/tutorials/maui-blazor-web-app.md | 128 +++++++++--------- 1 file changed, 61 insertions(+), 67 deletions(-) diff --git a/aspnetcore/blazor/hybrid/tutorials/maui-blazor-web-app.md b/aspnetcore/blazor/hybrid/tutorials/maui-blazor-web-app.md index 73deab20dab6..24079ade0b7d 100644 --- a/aspnetcore/blazor/hybrid/tutorials/maui-blazor-web-app.md +++ b/aspnetcore/blazor/hybrid/tutorials/maui-blazor-web-app.md @@ -5,16 +5,11 @@ description: Learn how to build a .NET MAUI Blazor Hybrid app with a Blazor Web monikerRange: '>= aspnetcore-8.0' ms.author: riande ms.custom: mvc -ms.date: 06/20/2024 +ms.date: 10/17/2024 uid: blazor/hybrid/tutorials/maui-blazor-web-app --- # Build a .NET MAUI Blazor Hybrid app with a Blazor Web App - - This article shows you how to build a .NET MAUI Blazor Hybrid app with a Blazor Web App that uses a shared user interface via a Razor class library (RCL). ## Prerequisites and preliminary steps @@ -73,8 +68,7 @@ Add new project to the solution with the **Blazor Web App** project template. Se * **Interactivity location**: **Global** * **Sample pages**: Unselected (disabled) - + The **Interactivity location** setting to **Global** is important because MAUI apps always run interactively and throw errors on Razor component pages that explicitly specify a render mode. If you don't use a global render mode, you must implement the approach described in the [Use Blazor render modes](#use-blazor-render-modes) section after following the guidance in this section. For more information, see [BlazorWebView needs a way to enable overriding ResolveComponentForRenderMode (`dotnet/aspnetcore` #51235)](https://github.com/dotnet/aspnetcore/issues/51235). @@ -299,7 +293,7 @@ For the Blazor Web App on the web client, the property values are assigned from `InteractiveRenderSettings.cs`: -:::code language="csharp" source="~/../blazor-samples/8.0/MauiBlazorWeb/MauiBlazorWeb.Shared/InteractiveRenderSettings.cs"::: +:::code language="csharp" source="~/../blazor-samples/9.0/MauiBlazorWeb/MauiBlazorWeb.Shared/InteractiveRenderSettings.cs"::: In `MauiProgram.CreateMauiApp` of `MauiProgram.cs`, call `ConfigureBlazorHybridRenderModes`: @@ -307,14 +301,15 @@ In `MauiProgram.CreateMauiApp` of `MauiProgram.cs`, call `ConfigureBlazorHybridR InteractiveRenderSettings.ConfigureBlazorHybridRenderModes(); ``` -In the RCL's `_Imports.razor` file, add the following global static `@using` directive to make the properties of the class available to components: +In the `_Imports.razor` file of the `.Shared` RCL, replace the `@using` statement for with an `@using` statement for `InteractiveRenderSettings` to make the properties of the `InteractiveRenderSettings` class available to components: -```razor -@using static InteractiveRenderSettings +```diff +- @using static Microsoft.AspNetCore.Components.Web.RenderMode ++ @using static InteractiveRenderSettings ``` > [!NOTE] -> The assignment of render modes via the RCL's `InteractiveRenderSettings` class properties differs from a typical standalone Blazor Web App. In a Blazor Web App, the render modes are normally provided by via the `@using static Microsoft.AspNetCore.Components.Web.RenderMode` statement in the Blazor Web App's `_Import` file. +> The assignment of render modes via the RCL's `InteractiveRenderSettings` class properties differs from a typical standalone Blazor Web App. In a Blazor Web App, the render modes are normally provided by in the Blazor Web App's `_Import` file. ### Per-page/component Auto interactivity @@ -340,7 +335,7 @@ For the Blazor Web App on the web client, the property values are assigned from `InteractiveRenderSettings.cs`: -:::code language="csharp" source="~/../blazor-samples/8.0/MauiBlazorWeb/MauiBlazorWeb.Shared/InteractiveRenderSettings.cs"::: +:::code language="csharp" source="~/../blazor-samples/9.0/MauiBlazorWeb/MauiBlazorWeb.Shared/InteractiveRenderSettings.cs"::: In `MauiProgram.CreateMauiApp` of `MauiProgram.cs`, call `ConfigureBlazorHybridRenderModes`: @@ -348,14 +343,15 @@ In `MauiProgram.CreateMauiApp` of `MauiProgram.cs`, call `ConfigureBlazorHybridR InteractiveRenderSettings.ConfigureBlazorHybridRenderModes(); ``` -In the RCL's `_Imports.razor` file, add the following global static `@using` directive to make the properties of the class available to components: +In the `_Imports.razor` file of the `.Shared.Client` RCL, replace the `@using` statement for with an `@using` statement for `InteractiveRenderSettings` to make the properties of the `InteractiveRenderSettings` class available to components: -```razor -@using static InteractiveRenderSettings +```diff +- @using static Microsoft.AspNetCore.Components.Web.RenderMode ++ @using static InteractiveRenderSettings ``` > [!NOTE] -> The assignment of render modes via the RCL's `InteractiveRenderSettings` class properties differs from a typical standalone Blazor Web App. In a Blazor Web App, the render modes are normally provided by via the `@using static Microsoft.AspNetCore.Components.Web.RenderMode` statement in the Blazor Web App's `_Import` file. +> The assignment of render modes via the RCL's `InteractiveRenderSettings` class properties differs from a typical standalone Blazor Web App. In a Blazor Web App, the render modes are normally provided by in the Blazor Web App's `_Import` file. ### Per-page/component WebAssembly interactivity @@ -405,7 +401,7 @@ For the Blazor Web App on the web client, the property values are assigned from `InteractiveRenderSettings.cs` (`.Shared.Client` RCL): -:::code language="csharp" source="~/../blazor-samples/8.0/MauiBlazorWeb/MauiBlazorWeb.Shared/InteractiveRenderSettings.cs"::: +:::code language="csharp" source="~/../blazor-samples/9.0/MauiBlazorWeb/MauiBlazorWeb.Shared/InteractiveRenderSettings.cs"::: A slightly different version of the `InteractiveRenderSettings` class is added to the `.Shared` RCL. In the class added to the `.Shared` RCL, `InteractiveRenderSettings.ConfigureBlazorHybridRenderModes` of the `.Shared.Client` RCL is called. This ensures that the render mode of WebAssembly components rendered on the MAUI client are unassigned (`null`) because they're interactive by default on the native client. @@ -444,14 +440,15 @@ In `MauiProgram.CreateMauiApp` of `MauiProgram.cs`, call `ConfigureBlazorHybridR InteractiveRenderSettings.ConfigureBlazorHybridRenderModes(); ``` -In the `_Imports.razor` file of the `.Shared.Client` RCL, add `@using static InteractiveRenderSettings` to make the properties of the `InteractiveRenderSettings` class available to components: +In the `_Imports.razor` file of the `.Shared.Client` RCL, replace the `@using` statement for with an `@using` statement for `InteractiveRenderSettings` to make the properties of the `InteractiveRenderSettings` class available to components: -```razor -@using static InteractiveRenderSettings +```diff +- @using static Microsoft.AspNetCore.Components.Web.RenderMode ++ @using static InteractiveRenderSettings ``` > [!NOTE] -> The assignment of render modes via the RCL's `InteractiveRenderSettings` class properties differs from a typical standalone Blazor Web App. In a Blazor Web App, the render modes are normally provided by via the `@using static Microsoft.AspNetCore.Components.Web.RenderMode` statement in the Blazor Web App's `_Import` file. +> The assignment of render modes via the RCL's `InteractiveRenderSettings` class properties differs from a typical standalone Blazor Web App. In a Blazor Web App, the render modes are normally provided by in the Blazor Web App's `_Import` file. :::moniker-end @@ -484,14 +481,15 @@ In `MauiProgram.CreateMauiApp` of `MauiProgram.cs`, call `ConfigureBlazorHybridR InteractiveRenderSettings.ConfigureBlazorHybridRenderModes(); ``` -In the RCL's `_Imports.razor` file, add the following global static `@using` directive to make the properties of the class available to components: +In the `_Imports.razor` file of the `.Shared` RCL, replace the `@using` statement for with an `@using` statement for `InteractiveRenderSettings` to make the properties of the `InteractiveRenderSettings` class available to components: -```razor -@using static InteractiveRenderSettings +```diff +- @using static Microsoft.AspNetCore.Components.Web.RenderMode ++ @using static InteractiveRenderSettings ``` > [!NOTE] -> The assignment of render modes via the RCL's `InteractiveRenderSettings` class properties differs from a typical standalone Blazor Web App. In a Blazor Web App, the render modes are normally provided by via the `@using static Microsoft.AspNetCore.Components.Web.RenderMode` statement in the Blazor Web App's `_Import` file. +> The assignment of render modes via the RCL's `InteractiveRenderSettings` class properties differs from a typical standalone Blazor Web App. In a Blazor Web App, the render modes are normally provided by in the Blazor Web App's `_Import` file. ### Per-page/component Auto interactivity @@ -525,14 +523,15 @@ In `MauiProgram.CreateMauiApp` of `MauiProgram.cs`, call `ConfigureBlazorHybridR InteractiveRenderSettings.ConfigureBlazorHybridRenderModes(); ``` -In the RCL's `_Imports.razor` file, add the following global static `@using` directive to make the properties of the class available to components: +In the `_Imports.razor` file of the `.Shared` RCL, replace the `@using` statement for with an `@using` statement for `InteractiveRenderSettings` to make the properties of the `InteractiveRenderSettings` class available to components: -```razor -@using static InteractiveRenderSettings +```diff +- @using static Microsoft.AspNetCore.Components.Web.RenderMode ++ @using static InteractiveRenderSettings ``` > [!NOTE] -> The assignment of render modes via the RCL's `InteractiveRenderSettings` class properties differs from a typical standalone Blazor Web App. In a Blazor Web App, the render modes are normally provided by via the `@using static Microsoft.AspNetCore.Components.Web.RenderMode` statement in the Blazor Web App's `_Import` file. +> The assignment of render modes via the RCL's `InteractiveRenderSettings` class properties differs from a typical standalone Blazor Web App. In a Blazor Web App, the render modes are normally provided by in the Blazor Web App's `_Import` file. ### Per-page/component WebAssembly interactivity @@ -621,14 +620,15 @@ In `MauiProgram.CreateMauiApp` of `MauiProgram.cs`, call `ConfigureBlazorHybridR InteractiveRenderSettings.ConfigureBlazorHybridRenderModes(); ``` -In the `_Imports.razor` file of the `.Shared.Client` RCL, add `@using static InteractiveRenderSettings` to make the properties of the `InteractiveRenderSettings` class available to components: +In the `_Imports.razor` file of the `.Shared.Client` RCL, replace the `@using` statement for with an `@using` statement for `InteractiveRenderSettings` to make the properties of the `InteractiveRenderSettings` class available to components: -```razor -@using static InteractiveRenderSettings +```diff +- @using static Microsoft.AspNetCore.Components.Web.RenderMode ++ @using static InteractiveRenderSettings ``` > [!NOTE] -> The assignment of render modes via the RCL's `InteractiveRenderSettings` class properties differs from a typical standalone Blazor Web App. In a Blazor Web App, the render modes are normally provided by via the `@using static Microsoft.AspNetCore.Components.Web.RenderMode` statement in the Blazor Web App's `_Import` file. +> The assignment of render modes via the RCL's `InteractiveRenderSettings` class properties differs from a typical standalone Blazor Web App. In a Blazor Web App, the render modes are normally provided by via in the Blazor Web App's `_Import` file. :::moniker-end @@ -636,13 +636,13 @@ In the `_Imports.razor` file of the `.Shared.Client` RCL, add `@using static Int The following example demonstrates how to use an interface to call into different implementations across the web app and the native (MAUI) app. The following example creates a component that displays the device form factor. Use the MAUI abstraction layer for native apps and provide an implementation for the web app. -In the Razor class library (RCL), an `Interfaces` folder contains an `IFormFactor` interface. +:::moniker range=">= aspnetcore-9.0" -`Interfaces/IFormFactor.cs`: +In the Razor class library (RCL), a `Services` folder contains an `IFormFactor` interface. -:::code language="csharp" source="~/../blazor-samples/8.0/MauiBlazorWeb/MauiBlazorWeb.Shared/Interfaces/IFormFactor.cs"::: +`Services/IFormFactor.cs`: -:::moniker range=">= aspnetcore-9.0" +:::code language="csharp" source="~/../blazor-samples/9.0/MauiBlazorWeb/MauiBlazorWeb.Shared/Services/IFormFactor.cs"::: The `Home` component (`Components/Pages/Home.razor`) of the RCL displays the form factor and platform. @@ -650,7 +650,7 @@ The `Home` component (`Components/Pages/Home.razor`) of the RCL displays the for ```razor @page "/" -@using MyApp.Shared.Services +@using MauiBlazorWeb.Shared.Services @inject IFormFactor FormFactor Home @@ -669,6 +669,12 @@ Welcome to your new app running on @factor using @platform. :::moniker range="< aspnetcore-9.0" +In the Razor class library (RCL), an `Interfaces` folder contains an `IFormFactor` interface. + +`Interfaces/IFormFactor.cs`: + +:::code language="csharp" source="~/../blazor-samples/8.0/MauiBlazorWeb/MauiBlazorWeb.Shared/Interfaces/IFormFactor.cs"::: + The following `DeviceFormFactor` component is present in the RCL's `Components` folder. `Components/Pages/DeviceFormFactor.razor`: @@ -693,47 +699,35 @@ The web and native apps contain the implementations for `IFormFactor`. In the Blazor Web App, a folder named `Services` contains the following `FormFactor.cs` file with the `FormFactor` implementation for web app use. -`Services/FormFactor.cs` (Blazor Web App project): +`Services/FormFactor.cs` (`MauiBlazorWeb.Web` project): -:::code language="csharp" source="~/../blazor-samples/8.0/MauiBlazorWeb/MauiBlazorWeb.Web/Services/FormFactor.cs"::: +:::moniker range=">= aspnetcore-9.0" -In the MAUI project, a folder named `Services` contains the following `FormFactor.cs` file with the `FormFactor` implementation for native use. The MAUI abstractions layer is used to write code that works on all native device platforms. +:::code language="csharp" source="~/../blazor-samples/9.0/MauiBlazorWeb/MauiBlazorWeb.Web/Services/FormFactor.cs"::: -`Services/FormFactor.cs` (MAUI project): +:::moniker-end -:::moniker range=">= aspnetcore-9.0" +:::moniker range="< aspnetcore-9.0" -```csharp -using MauiBlazorWeb.Shared.Interfaces; +:::code language="csharp" source="~/../blazor-samples/8.0/MauiBlazorWeb/MauiBlazorWeb.Web/Services/FormFactor.cs"::: -namespace MauiBlazorWeb.Services; +:::moniker-end -public class FormFactor : IFormFactor -{ - public string GetFormFactor() => DeviceInfo.Idiom.ToString(); +In the MAUI project, a folder named `Services` contains the following `FormFactor.cs` file with the `FormFactor` implementation for native use. The MAUI abstractions layer is used to write code that works on all native device platforms. - public string GetPlatform() => - DeviceInfo.Platform.ToString() + " - " + DeviceInfo.VersionString; -} -``` +:::moniker range=">= aspnetcore-9.0" -:::moniker-end +`Services/FormFactor.cs` (`MauiBlazorWeb` project): -:::moniker range="< aspnetcore-9.0" +:::code language="csharp" source="~/../blazor-samples/9.0/MauiBlazorWeb/MauiBlazorWeb/Services/FormFactor.cs"::: -```csharp -using MauiBlazorWeb.Shared.Interfaces; +:::moniker-end -namespace MauiBlazorWeb.Maui.Services; +:::moniker range="< aspnetcore-9.0" -public class FormFactor : IFormFactor -{ - public string GetFormFactor() => DeviceInfo.Idiom.ToString(); +`Services/FormFactor.cs` (`MauiBlazorWeb.Maui` project): - public string GetPlatform() => - DeviceInfo.Platform.ToString() + " - " + DeviceInfo.VersionString; -} -``` +:::code language="csharp" source="~/../blazor-samples/8.0/MauiBlazorWeb/MauiBlazorWeb.Maui/Services/FormFactor.cs"::: :::moniker-end From d4d3760b6013183a9a70121b4ff6d590f5d940fb Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Fri, 18 Oct 2024 08:02:14 -0400 Subject: [PATCH 8/8] Cross-link 9.0 sample code (#33872) --- aspnetcore/blazor/advanced-scenarios.md | 8 +- aspnetcore/blazor/blazor-ef-core.md | 40 ++++- .../cascading-values-and-parameters.md | 2 +- aspnetcore/blazor/file-downloads.md | 28 +++- aspnetcore/blazor/forms/binding.md | 70 +++++++++ aspnetcore/blazor/forms/index.md | 34 ++++- aspnetcore/blazor/forms/input-components.md | 32 +++- aspnetcore/blazor/forms/validation.md | 48 +++++- .../blazor/fundamentals/configuration.md | 16 +- .../blazor/fundamentals/handle-errors.md | 8 +- aspnetcore/blazor/fundamentals/index.md | 10 +- aspnetcore/blazor/fundamentals/logging.md | 16 +- aspnetcore/blazor/fundamentals/routing.md | 40 ++++- aspnetcore/blazor/host-and-deploy/server.md | 8 +- aspnetcore/blazor/images-and-documents.md | 24 ++- .../call-dotnet-from-javascript.md | 138 ++++++++++++++++-- .../call-javascript-from-dotnet.md | 132 +++++++++++++++-- .../security/blazor-web-app-with-entra.md | 4 +- aspnetcore/blazor/security/index.md | 4 - .../blazor/tutorials/build-a-blazor-app.md | 58 +++++++- .../build-a-blazor-app/9.0/Todo0.razor | 10 ++ .../build-a-blazor-app/9.0/Todo2.razor | 17 +++ .../build-a-blazor-app/9.0/Todo3.razor | 20 +++ .../build-a-blazor-app/9.0/Todo4.razor | 11 ++ .../build-a-blazor-app/9.0/Todo6.razor | 30 ++++ .../build-a-blazor-app/9.0/Todo7.razor | 9 ++ .../build-a-blazor-app/9.0/Todo8.razor | 33 +++++ 27 files changed, 772 insertions(+), 78 deletions(-) create mode 100644 aspnetcore/blazor/tutorials/build-a-blazor-app/9.0/Todo0.razor create mode 100644 aspnetcore/blazor/tutorials/build-a-blazor-app/9.0/Todo2.razor create mode 100644 aspnetcore/blazor/tutorials/build-a-blazor-app/9.0/Todo3.razor create mode 100644 aspnetcore/blazor/tutorials/build-a-blazor-app/9.0/Todo4.razor create mode 100644 aspnetcore/blazor/tutorials/build-a-blazor-app/9.0/Todo6.razor create mode 100644 aspnetcore/blazor/tutorials/build-a-blazor-app/9.0/Todo7.razor create mode 100644 aspnetcore/blazor/tutorials/build-a-blazor-app/9.0/Todo8.razor diff --git a/aspnetcore/blazor/advanced-scenarios.md b/aspnetcore/blazor/advanced-scenarios.md index 1880fa66af8e..a7d30c890927 100644 --- a/aspnetcore/blazor/advanced-scenarios.md +++ b/aspnetcore/blazor/advanced-scenarios.md @@ -33,7 +33,13 @@ In methods wi `BuiltContent.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/BuiltContent.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/BuiltContent.razor"::: diff --git a/aspnetcore/blazor/blazor-ef-core.md b/aspnetcore/blazor/blazor-ef-core.md index 59e5bd945677..931629e0f891 100644 --- a/aspnetcore/blazor/blazor-ef-core.md +++ b/aspnetcore/blazor/blazor-ef-core.md @@ -62,7 +62,13 @@ The sample demonstrates use of EF Core to handle optimistic concurrency. However The sample uses a local [SQLite](https://www.sqlite.org/index.html) database so that it can be used on any platform. The sample also configures database logging to show the SQL queries that are generated. This is configured in `appsettings.Development.json`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="json" source="~/../blazor-samples/9.0/BlazorWebAppEFCore/appsettings.Development.json"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="json" source="~/../blazor-samples/8.0/BlazorWebAppEFCore/appsettings.Development.json"::: @@ -167,7 +173,13 @@ In the preceding factory: The following example configures [SQLite](https://www.sqlite.org/index.html) and enables data logging. The code uses an extension method (`AddDbContextFactory`) to configure the database factory for DI and provide default options: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorWebAppEFCore/Program.cs" id="snippet1"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorWebAppEFCore/Program.cs" id="snippet1"::: @@ -207,7 +219,13 @@ In the home page of the sample app, `IDbContextFactory` is injec A `DbContext` is created using the factory (`DbFactory`) to delete a contact in the `DeleteContactAsync` method: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorWebAppEFCore/Components/Pages/Home.razor" id="snippet1"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorWebAppEFCore/Components/Pages/Home.razor" id="snippet1"::: @@ -274,7 +292,13 @@ You can use the factory to create a context and track it for the lifetime of the The sample app ensures the context is disposed when the component is disposed: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorWebAppEFCore/Components/Pages/EditContact.razor" id="snippet1"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorWebAppEFCore/Components/Pages/EditContact.razor" id="snippet1"::: @@ -306,7 +330,13 @@ The sample app ensures the context is disposed when the component is disposed: Finally, [`OnInitializedAsync`](xref:blazor/components/lifecycle) is overridden to create a new context. In the sample app, [`OnInitializedAsync`](xref:blazor/components/lifecycle) loads the contact in the same method: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorWebAppEFCore/Components/Pages/EditContact.razor" id="snippet2"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorWebAppEFCore/Components/Pages/EditContact.razor" id="snippet2"::: diff --git a/aspnetcore/blazor/components/cascading-values-and-parameters.md b/aspnetcore/blazor/components/cascading-values-and-parameters.md index c07560c5b8c5..dcd6efa16d71 100644 --- a/aspnetcore/blazor/components/cascading-values-and-parameters.md +++ b/aspnetcore/blazor/components/cascading-values-and-parameters.md @@ -111,7 +111,7 @@ The following `ThemeInfo` C# class specifies the theme information. :::moniker range=">= aspnetcore-9.0" -:::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/ThemeInfo.cs"::: +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/ThemeInfo.cs"::: :::moniker-end diff --git a/aspnetcore/blazor/file-downloads.md b/aspnetcore/blazor/file-downloads.md index 07baf576f636..e36a0e004eec 100644 --- a/aspnetcore/blazor/file-downloads.md +++ b/aspnetcore/blazor/file-downloads.md @@ -110,7 +110,13 @@ The following component: `FileDownload1.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/FileDownload1.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/FileDownload1.razor"::: @@ -159,7 +165,13 @@ The example in this section uses a download file named `quote.txt`, which is pla `wwwroot/files/quote.txt`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="text" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/wwwroot/files/quote.txt"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="text" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/wwwroot/files/quote.txt"::: @@ -203,7 +215,17 @@ The following example component downloads the file from the same origin that the `FileDownload2.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/FileDownload2.razor"::: + +For interactive components, the button in the preceding example calls the `DownloadFileFromURL` handler to invoke the JavaScript (JS) function `triggerFileDownload`. + +If the component adopts static server-side rendering (static SSR), add an event handler for the button ([`addEventListener` (MDN documentation)](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener)) to call `triggerFileDownload` following the guidance in . + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/FileDownload2.razor"::: diff --git a/aspnetcore/blazor/forms/binding.md b/aspnetcore/blazor/forms/binding.md index c6a7d4e44898..c902c3fe4324 100644 --- a/aspnetcore/blazor/forms/binding.md +++ b/aspnetcore/blazor/forms/binding.md @@ -238,8 +238,22 @@ The following example independently binds two forms to their models by form name `Starship6.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Starship6.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Starship6.razor"::: +:::moniker-end + +:::moniker range=">= aspnetcore-8.0" + ## Nest and bind forms The following guidance demonstrates how to nest and bind child forms. @@ -248,26 +262,82 @@ The following ship details class (`ShipDetails`) holds a description and length `ShipDetails.cs`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/ShipDetails.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" + :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/ShipDetails.cs"::: +:::moniker-end + +:::moniker range=">= aspnetcore-8.0" + The following `Ship` class names an identifier (`Id`) and includes the ship details. `Ship.cs`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Ship.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" + :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Ship.cs"::: +:::moniker-end + +:::moniker range=">= aspnetcore-8.0" + The following subform is used for editing values of the `ShipDetails` type. This is implemented by inheriting at the top of the component. ensures that the child component generates the correct form field names based on the model (`T`), where `T` in the following example is `ShipDetails`. `StarshipSubform.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/StarshipSubform.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/StarshipSubform.razor"::: +:::moniker-end + +:::moniker range=">= aspnetcore-8.0" + The main form is bound to the `Ship` class. The `StarshipSubform` component is used to edit ship details, bound as `Model!.Details`. `Starship7.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Starship7.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Starship7.razor"::: +:::moniker-end + +:::moniker range=">= aspnetcore-8.0" + ## Initialize form data with static SSR When a component adopts static SSR, the [`OnInitialized{Async}` lifecycle method](xref:blazor/components/lifecycle#component-initialization-oninitializedasync) and the [`OnParametersSet{Async}` lifecycle method](xref:blazor/components/lifecycle#after-parameters-are-set-onparameterssetasync) fire when the component is initially rendered and on every form POST to the server. To initialize form model values, confirm if the model already has data before assigning new model values in `OnParametersSet{Async}`, as the following example demonstrates. diff --git a/aspnetcore/blazor/forms/index.md b/aspnetcore/blazor/forms/index.md index c54b273808e1..ebaff94073a5 100644 --- a/aspnetcore/blazor/forms/index.md +++ b/aspnetcore/blazor/forms/index.md @@ -50,8 +50,22 @@ Standard HTML forms are supported. Create a form using the normal HTML `
` `StarshipPlainForm.razor`: +:::moniker-end + +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/StarshipPlainForm.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" + :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/StarshipPlainForm.razor"::: +:::moniker-end + +:::moniker range=">= aspnetcore-8.0" + In the preceding `StarshipPlainForm` component: * The form is rendered where the `` element appears. The form is named with the [`@formname`](xref:mvc/views/razor#formname) directive attribute, which uniquely identifies the form to the Blazor framework. @@ -84,10 +98,20 @@ A form is defined using the Blazor framework's component is rendered where the `` element appears. The form is named with the [`@formname`](xref:mvc/views/razor#formname) directive attribute, which uniquely identifies the form to the Blazor framework. @@ -158,7 +182,13 @@ In the next example, the preceding component is modified to create the form in t `Starship2.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Starship2.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Starship2.razor"::: diff --git a/aspnetcore/blazor/forms/input-components.md b/aspnetcore/blazor/forms/input-components.md index ca71258cc401..50d2fc020356 100644 --- a/aspnetcore/blazor/forms/input-components.md +++ b/aspnetcore/blazor/forms/input-components.md @@ -96,7 +96,13 @@ The following `Starship` type, which is used in several of this article's exampl `Starship.cs`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Starship.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Starship.cs"::: @@ -135,7 +141,13 @@ When the model property for the ship's classification (`Classification`) is set, `Starship3.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Starship3.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Starship3.razor"::: @@ -236,7 +248,13 @@ In the following example: `Starship4.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Starship4.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Starship4.razor"::: @@ -317,7 +335,13 @@ In the following example, the user must select at least two starship classificat :::moniker-end -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Starship5.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Starship5.razor"::: diff --git a/aspnetcore/blazor/forms/validation.md b/aspnetcore/blazor/forms/validation.md index 4e51e910989d..b74887a9c694 100644 --- a/aspnetcore/blazor/forms/validation.md +++ b/aspnetcore/blazor/forms/validation.md @@ -30,7 +30,13 @@ In the following component, the `HandleValidationRequested` handler method clear `Starship8.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Starship8.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Starship8.razor"::: @@ -191,7 +197,13 @@ When validation messages are set in the component, they're added to the validato `Starship9.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Starship9.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Starship9.razor"::: @@ -828,7 +840,13 @@ The `CustomInputText` component can be used anywhere instance into `ConfigExample.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_WebAssembly/Pages/ConfigExample.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_WebAssembly/Pages/ConfigExample.razor"::: @@ -180,7 +186,13 @@ Inject an instance into `MemoryConfig.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_WebAssembly/Pages/MemoryConfig.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_WebAssembly/Pages/MemoryConfig.razor"::: diff --git a/aspnetcore/blazor/fundamentals/handle-errors.md b/aspnetcore/blazor/fundamentals/handle-errors.md index 7233eb37a3de..4a8701b262c4 100644 --- a/aspnetcore/blazor/fundamentals/handle-errors.md +++ b/aspnetcore/blazor/fundamentals/handle-errors.md @@ -801,7 +801,13 @@ In the following example where is disposed in the `Dispose` method. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`CallDotnet2.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CallDotnet2.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `CallDotnet2.razor`: @@ -420,7 +444,15 @@ In the preceding example, the variable name `dotNetHelper` is arbitrary and can Provide the parameter list to the .NET method. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`CallDotnet3.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CallDotnet3.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `CallDotnet3.razor`: @@ -934,7 +966,13 @@ The following `HelloHelper` class has a JS-invokable .NET method named `GetHello `HelloHelper.cs`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/HelloHelper.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/HelloHelper.cs"::: @@ -968,7 +1006,13 @@ The `CallHelloHelperGetHelloMessage` method in the following `JsInteropClasses3` `JsInteropClasses3.cs`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/JsInteropClasses3.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/JsInteropClasses3.cs"::: @@ -1002,7 +1046,15 @@ To avoid a memory leak and allow garbage collection, the .NET object reference c When the **`Trigger .NET instance method`** button is selected in the following component, `JsInteropClasses3.CallHelloHelperGetHelloMessage` is called with the value of `name`. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`CallDotnet4.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CallDotnet4.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `CallDotnet4.razor`: @@ -1048,7 +1100,15 @@ The following image shows the rendered component with the name `Amy Pond` in the The preceding pattern shown in the `JsInteropClasses3` class can also be implemented entirely in a component. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`CallDotnet5.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CallDotnet5.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `CallDotnet5.razor`: @@ -1124,7 +1184,13 @@ The following `MessageUpdateInvokeHelper` class maintains a JS-invokable .NET me `MessageUpdateInvokeHelper.cs`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/MessageUpdateInvokeHelper.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/MessageUpdateInvokeHelper.cs"::: @@ -1176,7 +1242,13 @@ When a `ListItem1` component's **`InteropCall`** button is selected, `updateMess `ListItem1.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/ListItem1.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/ListItem1.razor"::: @@ -1210,7 +1282,15 @@ When a `ListItem1` component's **`InteropCall`** button is selected, `updateMess The following parent component includes four list items, each an instance of the `ListItem1` component. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`CallDotnet6.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CallDotnet6.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `CallDotnet6.razor`: @@ -1279,7 +1359,15 @@ In the following example: The following `assignDotNetHelper` JS function assigns the to an element in a property named `dotNetHelper`. The following `interopCall` JS function uses the for the passed element to invoke a .NET method named `UpdateMessage`. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`ListItem2.razor.js`: + +:::code language="javascript" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/ListItem2.razor.js"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `ListItem2.razor.js`: @@ -1318,7 +1406,13 @@ The is disposed when the compon `ListItem2.razor`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/ListItem2.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/ListItem2.razor"::: @@ -1350,7 +1444,15 @@ The is disposed when the compon The following parent component includes four list items, each an instance of the `ListItem2` component. -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`CallDotnet7.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CallDotnet7.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `CallDotnet7.razor`: @@ -1517,7 +1619,15 @@ Provide a `sendByteArray` JS function. The function is called statically, which :::moniker-end -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`CallDotnet8.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CallDotnet8.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `CallDotnet8.razor`: diff --git a/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md b/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md index 878eadd2dae2..afd5e98b167a 100644 --- a/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md +++ b/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md @@ -56,7 +56,15 @@ The following component: * Invokes the `convertArray` JS function with when selecting a button (**`Convert Array`**). * After the JS function is called, the passed array is converted into a string. The string is returned to the component for display (`text`). -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`CallJs1.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CallJs1.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `CallJs1.razor`: @@ -126,7 +134,15 @@ Provide a `displayTickerAlert1` JS function. The function is called with [!NOTE] > For general guidance on JS location and our recommendations for production apps, see . -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`CallJs7.razor` (parent component): + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CallJs7.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `CallJs7.razor` (parent component): @@ -818,7 +886,15 @@ For a parent component to make an element reference available to other component :::moniker-end -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`CallJs7.razor.cs`: + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_WebAssembly/Pages/CallJs7.razor.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `CallJs7.razor.cs`: @@ -862,7 +938,13 @@ In the preceding example, the namespace of the app is `BlazorSample`. If testing `SurveyPrompt.razor` (child component): -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/SurveyPrompt.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/SurveyPrompt.razor"::: @@ -894,7 +976,13 @@ In the preceding example, the namespace of the app is `BlazorSample`. If testing `SurveyPrompt.razor.cs`: -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +:::code language="csharp" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/SurveyPrompt.razor.cs"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" :::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/SurveyPrompt.razor.cs"::: @@ -1059,7 +1147,15 @@ Add the following `` element to the `` element markup ([location of :::moniker-end -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`CallJs8.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CallJs8.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `CallJs8.razor`: @@ -1271,7 +1367,15 @@ In the following example, the `nonFunction` JS function doesn't exist. When the > `Could not find 'nonFunction' ('nonFunction' was undefined).` -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-9.0" + +`CallJs11.razor`: + +:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/CallJs11.razor"::: + +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" `CallJs11.razor`: diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index c54632b75788..cbf90468b679 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -1,5 +1,5 @@ --- -title: Secure an ASP.NET Core Blazor Web App with Microsoft Entra +title: Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID author: guardrex description: Learn how to secure a Blazor WebAssembly App with Microsoft Entra ID. monikerRange: '>= aspnetcore-9.0' @@ -8,7 +8,7 @@ ms.custom: mvc ms.date: 10/07/2024 uid: blazor/security/blazor-web-app-entra --- -# Secure an ASP.NET Core Blazor Web App with Microsoft Entra +# Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID