You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: aspnetcore/blazor/components/cascading-values-and-parameters.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -517,4 +517,4 @@ The following `ExampleTabSet` component uses the `TabSet` component, which conta
517
517
## Additional resources
518
518
519
519
*[Generic type support: Explicit generic types based on ancestor components](xref:blazor/components/generic-type-support#explicit-generic-types-based-on-ancestor-components)
520
-
*[State management: Factor out the state preservation to a common location](xref:blazor/state-management?pivots=server#factor-out-the-state-preservation-to-a-common-location)
520
+
*[State management: Factor out state preservation to a common provider](xref:blazor/state-management?pivots=server#factor-out-state-preservation-to-a-common-provider)
Copy file name to clipboardExpand all lines: aspnetcore/blazor/javascript-interoperability/location-of-javascript.md
+9-9Lines changed: 9 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -33,17 +33,17 @@ Load JavaScript (JS) code using any of the following approaches:
33
33
34
34
:::moniker-end
35
35
36
+
## Location of `<script>` tags
37
+
36
38
:::moniker range=">= aspnetcore-8.0"
37
39
38
-
> [!WARNING]
39
-
> Only place a `<script>` tag in a component file (`.razor`) if the component is guaranteed to adopt [static server-side rendering (static SSR)](xref:blazor/fundamentals/index#client-and-server-rendering-concepts) because the `<script>` tag can't be updated dynamically.
40
+
Only place a `<script>` tag in a component file (`.razor`) if the component is guaranteed to adopt [static server-side rendering (static SSR)](xref:blazor/fundamentals/index#client-and-server-rendering-concepts) because the `<script>` tag can't be updated dynamically. Placing a `<script>` tag in a component file doesn't produce a compile-time warning or error, but script loading behavior might not match your expectations in components that don't adopt static SSR when the component is rendered.
40
41
41
42
:::moniker-end
42
43
43
44
:::moniker range="< aspnetcore-8.0"
44
45
45
-
> [!WARNING]
46
-
> Don't place a `<script>` tag in a component file (`.razor`) because the `<script>` tag can't be updated dynamically.
46
+
Don't place a `<script>` tag in a component file (`.razor`) because the `<script>` tag can't be updated dynamically. Placing a `<script>` tag in a component file produces a compile-time error.
47
47
48
48
:::moniker-end
49
49
@@ -61,7 +61,7 @@ Load JavaScript (JS) code using any of the following approaches:
61
61
62
62
:::moniker-end
63
63
64
-
###Load a script in `<head>` markup
64
+
## Load a script in `<head>` markup
65
65
66
66
*The approach in this section isn't generally recommended.*
67
67
@@ -84,7 +84,7 @@ Loading JS from the `<head>` isn't the best approach for the following reasons:
84
84
* JS interop may fail if the script depends on Blazor. We recommend loading scripts using one of the other approaches, not via the `<head>` markup.
85
85
* The page may become interactive slower due to the time it takes to parse the JS in the script.
86
86
87
-
###Load a script in `<body>` markup
87
+
## Load a script in `<body>` markup
88
88
89
89
Place the JavaScript tags (`<script>...</script>`) inside the [closing `</body>` element](xref:blazor/project-structure#location-of-head-and-body-content) after the Blazor script reference:
90
90
@@ -105,7 +105,7 @@ Place the JavaScript tags (`<script>...</script>`) inside the [closing `</body>`
105
105
106
106
:::moniker range=">= aspnetcore-6.0"
107
107
108
-
###Load a script from an external JavaScript file (`.js`) collocated with a component
108
+
## Load a script from an external JavaScript file (`.js`) collocated with a component
@@ -170,15 +170,15 @@ For more information, see <xref:blazor/components/class-libraries>.
170
170
171
171
:::moniker range=">= aspnetcore-6.0"
172
172
173
-
###Inject a script before or after Blazor starts
173
+
## Inject a script before or after Blazor starts
174
174
175
175
To ensure scripts load before or after Blazor starts, use a JavaScript initializer. For more information and examples, see <xref:blazor/fundamentals/startup#javascript-initializers>.
176
176
177
177
:::moniker-end
178
178
179
179
:::moniker range="< aspnetcore-6.0"
180
180
181
-
###Inject a script after Blazor starts
181
+
## Inject a script after Blazor starts
182
182
183
183
To inject a script after Blazor starts, chain to the `Promise` that results from a manual start of Blazor. For more information and an example, see <xref:blazor/fundamentals/startup#inject-a-script-after-blazor-starts>.
Copy file name to clipboardExpand all lines: aspnetcore/blazor/performance.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -228,7 +228,9 @@ To reduce parameter load, bundle multiple parameters in a custom class. For exam
228
228
}
229
229
```
230
230
231
-
However, consider that it might be an improvement not to have a table cell component, as shown in the preceding example, and instead [inline its logic into the parent component](#inline-child-components-into-their-parents).
231
+
However, keep in mind that bundling primitive parameters into a class isn't always an advantage. While it can reduce parameter count, it also impacts how change detection and rendering behave. Passing non-primitive parameters always triggers a re-render, because Blazor can't know whether arbitrary objects have internally mutable state, whereas passing primitive parameters only triggers a re-render if their values have actually changed.
232
+
233
+
Also, consider that it might be an improvement not to have a table cell component, as shown in the preceding example, and instead [inline its logic into the parent component](#inline-child-components-into-their-parents).
232
234
233
235
> [!NOTE]
234
236
> When multiple approaches are available for improving performance, benchmarking the approaches is usually required to determine which approach yields the best results.
Copy file name to clipboardExpand all lines: aspnetcore/blazor/security/interactive-server-side-rendering.md
+11Lines changed: 11 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -391,10 +391,21 @@ In addition to the safeguards that the framework implements, the app must be cod
391
391
392
392
For a XSS vulnerability to exist, the app must incorporate user input in the rendered page. Blazor executes a compile-time step where the markup in a `.razor` file is transformed into procedural C# logic. At runtime, the C# logic builds a *render tree* describing the elements, text, and child components. This is applied to the browser's DOM via a sequence of JavaScript instructions (or is serialized to HTML in the case of prerendering):
393
393
394
+
:::moniker range=">= aspnetcore-8.0"
395
+
396
+
* User input rendered via normal Razor syntax (for example, `@someStringValue`) doesn't expose a XSS vulnerability because the Razor syntax is added to the DOM via commands that can only write text. Even if the value includes HTML markup, the value is displayed as static text. When prerendering, the output is HTML-encoded, which also displays the content as static text.
397
+
* Component authors can author components in C# without using Razor. The component author is responsible for using the correct APIs when emitting output. For example, use `builder.AddContent(0, someUserSuppliedString)` and *not*`builder.AddMarkupContent(0, someUserSuppliedString)`, as the latter could create a XSS vulnerability.
398
+
399
+
:::moniker-end
400
+
401
+
:::moniker range="< aspnetcore-8.0"
402
+
394
403
* User input rendered via normal Razor syntax (for example, `@someStringValue`) doesn't expose a XSS vulnerability because the Razor syntax is added to the DOM via commands that can only write text. Even if the value includes HTML markup, the value is displayed as static text. When prerendering, the output is HTML-encoded, which also displays the content as static text.
395
404
* Script tags aren't allowed and shouldn't be included in the app's component render tree. If a script tag is included in a component's markup, a compile-time error is generated.
396
405
* Component authors can author components in C# without using Razor. The component author is responsible for using the correct APIs when emitting output. For example, use `builder.AddContent(0, someUserSuppliedString)` and *not*`builder.AddMarkupContent(0, someUserSuppliedString)`, as the latter could create a XSS vulnerability.
397
406
407
+
:::moniker-end
408
+
398
409
Consider further mitigating XSS vulnerabilities. For example, implement a restrictive [Content Security Policy (CSP)](https://developer.mozilla.org/docs/Web/HTTP/CSP). For more information, see <xref:blazor/security/content-security-policy>.
399
410
400
411
For more information, see <xref:security/cross-site-scripting>.
In the <xref:System.Text.Json.JsonSerializerOptions>, add the <xref:System.Text.Json.JsonSerializerOptions.DefaultIgnoreCondition> option set to <xref:System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull?displayProperty=nameWithType>, which avoids serializing null properties:
Copy file name to clipboardExpand all lines: aspnetcore/blazor/state-management.md
+40-17Lines changed: 40 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -399,11 +399,17 @@ else
399
399
400
400
:::moniker-end
401
401
402
-
### Factor out the state preservation to a common location
402
+
### Factor out state preservation to a common provider
403
403
404
404
If many components rely on browser-based storage, implementing state provider code many times creates code duplication. One option for avoiding code duplication is to create a *state provider parent component* that encapsulates the state provider logic. Child components can work with persisted data without regard to the state persistence mechanism.
405
405
406
-
In the following example of a `CounterStateProvider` component, counter data is persisted to `sessionStorage`:
406
+
In the following example of a `CounterStateProvider` component, counter data is persisted to `sessionStorage`, and it handles the loading phase by not rendering its child content until state loading is complete.
407
+
408
+
The `CounterStateProvider` component deals with prerendering by not loading state until after component rendering in the [`OnAfterRenderAsync` lifecycle method](xref:blazor/components/lifecycle#after-component-render-onafterrenderasync), which doesn't execute during prerendering.
409
+
410
+
The approach in this section isn't capable of triggering rerendering of multiple subscribed components on the same page. If one subscribed component changes the state, it rerenders and can display the updated state, but a different component on the same page displaying that state displays stale data until its own next rerender. Therefore, the approach described in this section is best suited to using state in a single component on the page.
> For more information on <xref:Microsoft.AspNetCore.Components.RenderFragment>, see <xref:blazor/components/index#child-content-render-fragments>.
491
519
492
-
The `CounterStateProvider` component handles the loading phase by not rendering its child content until state loading is complete.
493
-
494
520
:::moniker range=">= aspnetcore-8.0"
495
521
496
522
To make the state accessible to all components in an app, wrap the `CounterStateProvider` component around the <xref:Microsoft.AspNetCore.Components.Routing.Router> (`<Router>...</Router>`) in the `Routes` component with global interactive server-side rendering (interactive SSR).
@@ -541,17 +567,14 @@ Wrapped components receive and can modify the persisted counter state. The follo
541
567
{
542
568
if (CounterStateProvider is not null)
543
569
{
544
-
CounterStateProvider.CurrentCount++;
545
-
await CounterStateProvider.SaveChangesAsync();
570
+
await CounterStateProvider.IncrementCount();
546
571
}
547
572
}
548
573
}
549
574
```
550
575
551
576
The preceding component isn't required to interact with `ProtectedBrowserStorage`, nor does it deal with a "loading" phase.
552
577
553
-
To deal with prerendering as described earlier, `CounterStateProvider` can be amended so that all of the components that consume the counter data automatically work with prerendering. For more information, see the [Handle prerendering](#handle-prerendering) section.
554
-
555
578
In general, the *state provider parent component* pattern is recommended:
556
579
557
580
* To consume state across many components.
@@ -791,7 +814,7 @@ When implementing custom state storage, a useful approach is to adopt [cascading
791
814
792
815
## Troubleshoot
793
816
794
-
In a custom state management service, a callback invoked outside of Blazor's synchronization context must wrap the logic of the callback in <xref:Microsoft.AspNetCore.Components.ComponentBase.InvokeAsync%2A?displayProperty=nameWithType> to move it onto the renderer's synchronization context.
817
+
When using a custom state management service where you want to support state modifications from outside Blazor's synchronization context (for example from a timer or a background service), all consuming components must wrap the <xref:Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged%2A> call in <xref:Microsoft.AspNetCore.Components.ComponentBase.InvokeAsync%2A?displayProperty=nameWithType>. This ensures the change notification is handled on the renderer's synchronization context.
795
818
796
819
When the state management service doesn't call <xref:Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged%2A> on Blazor's synchronization context, the following error is thrown:
Copy file name to clipboardExpand all lines: aspnetcore/blazor/tutorials/movie-database-app/part-2.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -319,7 +319,7 @@ EF Core adopts the *code-first* approach for database design and maintenance:
319
319
* Entity classes are created and updated first in the app.
320
320
* The database is created and updated from the app's entity classes.
321
321
322
-
This is the reverse procedure of *database-first* approaches, where the database is designed, built, and updated first. Adopting EF Core's code-first approach speeds up the process of app development because most of the difficult and time-consuming database creation and management procedures are handled transparently by the EF Core tooling, so you can focus on app development.
322
+
This is the reverse procedure of *database-first* approaches, where the database is designed, built, and updated first. Adopting EF Core's code-first approach aims to speed up the process of app development because most of the difficult and time-consuming database creation and management procedures are handled transparently by the EF Core tooling, so you can focus on app development.
0 commit comments