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
docs: add 'migration shim, not destination' philosophy to ViewState
- Add warning admonition and comparison table to ViewStateAndPostBack.md
showing how BWFC ViewState differs from Web Forms ViewState (opt-in,
per-component, dirty-tracked, encrypted by default)
- Add 'Graduating Off ViewState' section with before/after examples
showing how to refactor toward native Blazor patterns
- Update XML doc comments on ViewStateDictionary and BaseWebFormsComponent
to reinforce the migration shim messaging
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy file name to clipboardExpand all lines: docs/UtilityFeatures/ViewStateAndPostBack.md
+89Lines changed: 89 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,8 @@
1
1
# ViewState and PostBack Shim
2
2
3
+
!!! warning "Migration Shim — Not a Destination"
4
+
ViewState and IsPostBack are **migration compatibility features**. They exist so your Web Forms code-behind logic compiles and runs correctly in Blazor with minimal changes. Once your application is running, you should **refactor toward native Blazor patterns** — `[Parameter]` properties, component fields, and cascading values. See [Graduating Off ViewState](#graduating-off-viewstate) below.
5
+
3
6
## Overview
4
7
5
8
The ViewState and PostBack shim features enable seamless migration of ASP.NET Web Forms applications to Blazor by emulating the familiar `ViewState` dictionary and `IsPostBack` pattern. These features bridge the gap between traditional stateless HTTP POST workflows and Blazor's component-based stateful architecture.
@@ -11,6 +14,20 @@ The ViewState and PostBack shim features enable seamless migration of ASP.NET We
11
14
-**Hidden Field Persistence** — Automatic round-tripping of ViewState through protected form fields in SSR
12
15
-**Form State Continuity** — Seamless state management across SSR and ServerInteractive transitions
13
16
17
+
### How This Differs from Web Forms ViewState
18
+
19
+
The original Web Forms ViewState was a source of well-known problems: page bloat, security vulnerabilities, and invisible performance costs. Our implementation is fundamentally different:
20
+
21
+
| Concern | Web Forms ViewState | BWFC ViewState Shim |
|**Visibility**| No insight into payload size |**Size warnings** logged when threshold exceeded |
29
+
|**Interactive mode**| N/A |**In-memory only** — no serialization overhead |
30
+
14
31
---
15
32
16
33
## ViewStateDictionary
@@ -607,6 +624,78 @@ public partial class ProductPage : System.Web.UI.Page
607
624
608
625
---
609
626
627
+
## Graduating Off ViewState
628
+
629
+
ViewState gets your Web Forms code running in Blazor. The next step is refactoring to native Blazor patterns. Here's how to migrate each common ViewState usage:
630
+
631
+
### Simple Values → Component Fields
632
+
633
+
=== "ViewState (Migration)"
634
+
635
+
```csharp
636
+
// Web Forms pattern preserved during migration
637
+
public int SelectedDepartmentId
638
+
{
639
+
get => ViewState.GetValueOrDefault<int>("SelectedDepartmentId");
640
+
set => ViewState.Set("SelectedDepartmentId", value);
641
+
}
642
+
```
643
+
644
+
=== "Native Blazor (Target)"
645
+
646
+
```csharp
647
+
// Refactored: simple field, no serialization overhead
648
+
private int _selectedDepartmentId;
649
+
```
650
+
651
+
### First-Load Guards → OnInitialized
652
+
653
+
=== "ViewState (Migration)"
654
+
655
+
```csharp
656
+
protected override void OnInitialized()
657
+
{
658
+
if (!IsPostBack)
659
+
{
660
+
ViewState["Products"] = LoadProducts();
661
+
}
662
+
}
663
+
```
664
+
665
+
=== "Native Blazor (Target)"
666
+
667
+
```csharp
668
+
// OnInitialized already runs once per component instance
669
+
protected override void OnInitialized()
670
+
{
671
+
_products = LoadProducts();
672
+
}
673
+
```
674
+
675
+
### Cross-Component State → Cascading Values or DI Services
676
+
677
+
=== "ViewState (Migration)"
678
+
679
+
```csharp
680
+
// Parent stores state in ViewState, child reads it
681
+
ViewState["SelectedCategory"] = category;
682
+
```
683
+
684
+
=== "Native Blazor (Target)"
685
+
686
+
```razor
687
+
<!-- Parent cascades value to children -->
688
+
<CascadingValue Value="@_selectedCategory">
689
+
@ChildContent
690
+
</CascadingValue>
691
+
```
692
+
693
+
### When ViewState Is Still Appropriate
694
+
695
+
ViewState remains useful for **SSR form round-trips** where you need state to survive an HTTP POST without JavaScript. This is a legitimate pattern in SSR Blazor — similar to hidden fields in any web framework. The key difference from Web Forms: you're choosing to use it, not having it imposed on every control.
696
+
697
+
---
698
+
610
699
## See Also
611
700
612
701
-[WebFormsPage](WebFormsPage.md) — Page-level wrapper combining naming scope and theming
0 commit comments