Skip to content
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ DocFX requires:

## Voice and tone

Our goal is to write documentation that is easily understandable by the widest possible audience. To that end, we established guidelines for writing style that we ask our contributors to follow. For more information, see [Voice and tone guidelines](https://github.com/dotnet/docs/blob/main/styleguide/voice-tone.md) in the .NET repo.
Our goal is to write documentation that is easily understandable by the widest possible audience. To that end, we established guidelines for writing style that we ask our contributors to follow. For more information, see [Voice and tone guidelines](/contribute/content/dotnet/dotnet-voice-tone).

## Microsoft Writing Style Guide

Expand Down
107 changes: 3 additions & 104 deletions aspnetcore/blazor/components/prerender.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,10 @@ To preserve prerendered state, use the `[SupplyParameterFromPersistentComponentS

By default, properties are serialized using the <xref:System.Text.Json?displayProperty=fullName> serializer with default settings. Serialization isn't trimmer safe and requires preservation of the types used. For more information, see <xref:blazor/host-and-deploy/configure-trimmer>.

The following example demonstrates the general pattern, where the `{TYPE}` placeholder represents the type of data to persist.
The following counter component persists counter state during prerendering and retrieves the state to initialize the component:

```razor
@code {
[SupplyParameterFromPersistentComponentState]
public {TYPE} Data { get; set; }

protected override async Task OnInitializedAsync()
{
Data ??= await ...;
}
}
```

The following counter component example persists counter state during prerendering and retrieves the state to initialize the component.
* The `[SupplyParameterFromPersistentComponentState]` attribute is applied to the `CounterState` type (`State`).
* The counter's state is assigned when `null` in `OnInitialized` and restored automatically when the component renders interactively.

`PrerenderedCounter2.razor`:

Expand Down Expand Up @@ -252,51 +241,6 @@ Serialized properties are identified from the actual service instance:

As an alternative to using the declarative model for persisting state with the `[SupplyParameterFromPersistentComponentState]` attribute, you can use the <xref:Microsoft.AspNetCore.Components.PersistentComponentState> service directly, which offers greater flexibility for complex state persistence scenarios. Call <xref:Microsoft.AspNetCore.Components.PersistentComponentState.RegisterOnPersisting%2A?displayProperty=nameWithType> to register a callback to persist the component state during prerendering. The state is retrieved when the component renders interactively. Make the call at the end of initialization code in order to avoid a potential race condition during app shutdown.

The following example demonstrates the general pattern:

* The `{TYPE}` placeholder represents the type of data to persist.
* The `{TOKEN}` placeholder is a state identifier string. Consider using `nameof({VARIABLE})`, where the `{VARIABLE}` placeholder is the name of the variable that holds the state. Using [`nameof()`](/dotnet/csharp/language-reference/operators/nameof) for the state identifier avoids the use of a quoted string.

```razor
@implements IDisposable
@inject PersistentComponentState ApplicationState

...

@code {
private {TYPE} data;
private PersistingComponentStateSubscription persistingSubscription;

protected override async Task OnInitializedAsync()
{
if (!ApplicationState.TryTakeFromJson<{TYPE}>(
"{TOKEN}", out var restored))
{
data = await ...;
}
else
{
data = restored!;
}

// Call at the end to avoid a potential race condition at app shutdown
persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
}

private Task PersistData()
{
ApplicationState.PersistAsJson("{TOKEN}", data);

return Task.CompletedTask;
}

void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
```

The following counter component example persists counter state during prerendering and retrieves the state to initialize the component.

`PrerenderedCounter3.razor`:
Expand Down Expand Up @@ -366,51 +310,6 @@ When the component executes, `currentCount` is only set once during prerendering

To preserve prerendered state, decide what state to persist using the <xref:Microsoft.AspNetCore.Components.PersistentComponentState> service. <xref:Microsoft.AspNetCore.Components.PersistentComponentState.RegisterOnPersisting%2A?displayProperty=nameWithType> registers a callback to persist the component state during prerendering. The state is retrieved when the component renders interactively. Make the call at the end of initialization code in order to avoid a potential race condition during app shutdown.

The following example demonstrates the general pattern:

* The `{TYPE}` placeholder represents the type of data to persist.
* The `{TOKEN}` placeholder is a state identifier string. Consider using `nameof({VARIABLE})`, where the `{VARIABLE}` placeholder is the name of the variable that holds the state. Using [`nameof()`](/dotnet/csharp/language-reference/operators/nameof) for the state identifier avoids the use of a quoted string.

```razor
@implements IDisposable
@inject PersistentComponentState ApplicationState

...

@code {
private {TYPE} data;
private PersistingComponentStateSubscription persistingSubscription;

protected override async Task OnInitializedAsync()
{
if (!ApplicationState.TryTakeFromJson<{TYPE}>(
"{TOKEN}", out var restored))
{
data = await ...;
}
else
{
data = restored!;
}

// Call at the end to avoid a potential race condition at app shutdown
persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
}

private Task PersistData()
{
ApplicationState.PersistAsJson("{TOKEN}", data);

return Task.CompletedTask;
}

void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
```

The following counter component example persists counter state during prerendering and retrieves the state to initialize the component.

`PrerenderedCounter2.razor`:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ When a Blazor WebAssembly app loads in the browser, the app downloads boot resou
* .NET runtime and assemblies
* Locale specific data

Except for Blazor's boot manifest file (`dotnet.boot.js` in .NET 10 or later, `blazor.boot.json` prior to .NET 10), WebAssembly .NET runtime and app bundle files are cached on clients. The Blazor boot configuration contains a manifest of the files that make up the app that must be downloaded along with a hash of the file's content that's used to detect whether any of the boot resources have changed. Blazor caches downloaded files using the browser [Cache](https://developer.mozilla.org/docs/Web/API/Cache) API.
Except for Blazor's boot manifest file (`blazor.boot.json` ) prior to the release of .NET 10, WebAssembly .NET runtime and app bundle files are cached on clients. The Blazor boot configuration, inlined into `dotnet.js` in .NET 10 or later, contains a manifest of the files that make up the app that must be downloaded along with a hash of the file's content that's used to detect whether any of the boot resources have changed. Blazor caches downloaded files using the browser [Cache](https://developer.mozilla.org/docs/Web/API/Cache) API.

When Blazor WebAssembly downloads an app's startup files, it instructs the browser to perform integrity checks on the responses. Blazor sends SHA-256 hash values for DLL (`.dll`), WebAssembly (`.wasm`), and other files in the Blazor boot configuration, which isn't cached on clients. The file hashes of cached files are compared to the hashes in the Blazor boot configuration. For cached files with a matching hash, Blazor uses the cached files. Otherwise, files are requested from the server. After a file is downloaded, its hash is checked again for integrity validation. An error is generated by the browser if any downloaded file's integrity check fails.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ The approach demonstrated in this article serves as a starting point for develop

The approach described in this article is used by the *experimental* [`Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle` package (NuGet.org)](https://www.nuget.org/packages/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle) for apps targeting .NET 6 or later. The package contains MSBuild targets to customize the Blazor publish output and a [JavaScript initializer](xref:blazor/js-interop/index#javascript-initializers) to use a custom [boot resource loader](xref:blazor/fundamentals/startup#load-boot-resources), each of which are described in detail later in this article.

[Experimental code (includes the NuGet package reference source and `CustomPackagedApp` sample app)](https://github.com/aspnet/AspLabs/tree/main/src/BlazorWebAssemblyCustomInitialization)

> [!WARNING]
> Experimental and preview features are provided for the purpose of collecting feedback and aren't supported for production use.

Expand Down
2 changes: 2 additions & 0 deletions aspnetcore/blazor/security/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,8 @@ To handle the case where the user must satisfy several policies simultaneously,

Claims-based authorization is a special case of policy-based authorization. For example, you can define a policy that requires users to have a certain claim. For more information, see <xref:security/authorization/policies>.

If both <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView.Roles> and <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView.Policy> are set, authorization succeeds only when both conditions are satisfied. That is, the user must belong to at least one of the specified roles *and* meet the requirements defined by the policy.

If neither <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView.Roles> nor <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView.Policy> is specified, <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView> uses the default policy:

* Authenticated (signed-in) users are authorized.
Expand Down
10 changes: 5 additions & 5 deletions aspnetcore/data/ef-rp/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ This is the first in a series of tutorials that show how to use Entity Framework

# [Visual Studio](#tab/visual-studio)

[!INCLUDE[VS prereqs](~/includes/net-prereqs-vs-6.0.md)]
[!INCLUDE[VS prereqs](~/includes/net-prereqs-vs-latest.md)]

### Database engines

Expand Down Expand Up @@ -559,15 +559,15 @@ This is the first in a series of tutorials that show how to use Entity Framework

# [Visual Studio](#tab/visual-studio)

[!INCLUDE[VS prereqs](~/includes/net-core-prereqs-vs-5.0.md)]
[!INCLUDE[VS prereqs](~/includes/net-prereqs-vs-latest.md)]

### Database engines

The Visual Studio instructions use [SQL Server LocalDB](/sql/database-engine/configure-windows/sql-server-2016-express-localdb), a version of SQL Server Express that runs only on Windows.

# [Visual Studio Code](#tab/visual-studio-code)

[!INCLUDE[VS Code prereqs](~/includes/net-core-prereqs-vsc-5.0.md)]
[!INCLUDE[VS Code prereqs](~/includes/net-prereqs-vsc-latest.md)]

Consider downloading and installing a third-party tool for managing and viewing a SQLite database, such as [DB Browser for SQLite](https://sqlitebrowser.org/).

Expand Down Expand Up @@ -1073,11 +1073,11 @@ This is the first in a series of tutorials that show how to use Entity Framework

# [Visual Studio](#tab/visual-studio)

[!INCLUDE[VS prereqs](~/includes/net-core-prereqs-vs-3.0.md)]
[!INCLUDE[VS prereqs](~/includes/net-prereqs-vs-latest.md)]

# [Visual Studio Code](#tab/visual-studio-code)

[!INCLUDE[VS Code prereqs](~/includes/net-core-prereqs-vsc-3.0.md)]
[!INCLUDE[VS Code prereqs](~/includes/net-prereqs-vsc-latest.md)]

---

Expand Down
9 changes: 4 additions & 5 deletions aspnetcore/data/scaffold_RP.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ content_well_notification: AI-contribution
ai-usage: ai-assisted
uid: data/dotnet-scaffold-rp
---

# Scaffold a data model with dotnet scaffold in a Razor Pages project

The CLI tool, [dotnet scaffold](https://www.nuget.org/packages/Microsoft.dotnet-scaffold) creates data access UI for many .NET project types, such as API, Aspire, Blazor, MVC, and Razor Pages. `dotnet scaffold` can be run interactively or as a command line tool via passing parameter values.
Expand Down Expand Up @@ -39,7 +38,7 @@ To navigate the UI, use the:

## Create and scaffold a data model in a Razor Pages project

If you have any problems with the following steps, see [Tutorial: Create a Razor Pages web app with ASP.NET Core](/aspnet/core/tutorials/razor-pages/) and select the **Visual Studio Code** tab.
If you have any problems with the following steps, see <xref:tutorials/razor-pages/index?tabs=visual-studio-code>.

1. Run the following commands to create a Razor Pages project and navigate to the projects folder:
```dotnetcli
Expand Down Expand Up @@ -78,7 +77,7 @@ In The preceding commands:

* `dotnet tool uninstall --global dotnet-ef` uninstalls the `dotnet-ef` tool. Uninstalling ensures the latest tool is successfully installed. If `dotnet-ef` isn't installed, an error messages **A tool with the package Id 'dotnet-ef' could not be found.** You can ignore this message.
* `dotnet tool install --global dotnet-ef` installs globally the `dotnet-ef` tool.
* `dotnet ef migrations add initialMigration` adds the initial migration. For more information, see [Create the initial database schema using EF's migration feature](/aspnet/core/tutorials/razor-pages/model&tabs=visual-studio-code)
* `dotnet ef migrations add initialMigration` adds the initial migration. For more information, see <xref:tutorials/razor-pages/model?tabs=visual-studio-code>.
* `dotnet ef database update` applies the migrations to the database.

Run the app:
Expand All @@ -94,5 +93,5 @@ Run the app:

* [dotnet scaffold repo on GitHub](https://github.com/dotnet/Scaffolding)
* [How to manage .NET tools](/dotnet/core/tools/global-tools)
* [Microsoft.dotnet-scaffold](https://www.nuget.org/packages/Microsoft.dotnet-scaffold) NuGet package.
* [Detailed tutorial on EF scaffolding Razor Pages](/aspnet/core/data/scaffold_rp)
* [`Microsoft.dotnet-scaffold`](https://www.nuget.org/packages/Microsoft.dotnet-scaffold) NuGet package.
* <xref:data/dotnet-scaffold-rp>
4 changes: 2 additions & 2 deletions aspnetcore/fundamentals/app-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ To enable the session-based TempData provider, use the <xref:Microsoft.Extension

A limited amount of data can be passed from one request to another by adding it to the new request's query string. This is useful for capturing state in a persistent manner that allows links with embedded state to be shared through email or social networks. Because URL query strings are public, never use query strings for sensitive data.

In addition to unintended sharing, including data in query strings can expose the app to [Cross-Site Request Forgery (CSRF)](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) attacks. Any preserved session state must protect against CSRF attacks. For more information, see <xref:security/anti-request-forgery>.
In addition to unintended sharing, including data in query strings can expose the app to [Cross-Site Request Forgery (CSRF)](https://owasp.org/www-community/attacks/csrf) attacks. Any preserved session state must protect against CSRF attacks. For more information, see <xref:security/anti-request-forgery>.

## Hidden fields

Expand Down Expand Up @@ -507,7 +507,7 @@ To enable the session-based TempData provider, use the <xref:Microsoft.Extension

A limited amount of data can be passed from one request to another by adding it to the new request's query string. This is useful for capturing state in a persistent manner that allows links with embedded state to be shared through email or social networks. Because URL query strings are public, never use query strings for sensitive data.

In addition to unintended sharing, including data in query strings can expose the app to [Cross-Site Request Forgery (CSRF)](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) attacks. Any preserved session state must protect against CSRF attacks. For more information, see <xref:security/anti-request-forgery>.
In addition to unintended sharing, including data in query strings can expose the app to [Cross-Site Request Forgery (CSRF)](https://owasp.org/www-community/attacks/csrf) attacks. Any preserved session state must protect against CSRF attacks. For more information, see <xref:security/anti-request-forgery>.

## Hidden fields

Expand Down
Loading
Loading