[Validation] Components that refuse to be cached in CacheView
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
**Scenario contact:** @dariatiurina
## Scenario
Some components cannot be cached and cannot safely run live either. `[CacheBehavior(CacheBehavior.Throw)]` makes such a component refuse to render inside a `CacheView`, and `[CacheCondition]` names the vary-by dimensions that make it safe after all. Two framework components already carry these: `AuthorizeView` needs `VaryByUser`, and `QuickGrid` needs `VaryByQuery`. Nesting one `CacheView` inside another is refused outright.
Validate that each refusal names the component and a way forward, that following the message actually resolves it, and that a component author can apply the same attributes to their own components.
## Minimum build
.NET 11 RC1.
## Configurations to cover
* Blazor Web App
* [x] Static SSR
* [ ] Interactive Server
* [ ] Interactive WebAssembly
* [ ] Interactive Auto
* [ ] Standalone WebAssembly
* [ ] Hybrid (MAUI)
## Also exercise
* [ ] Published output
* [ ] An existing .NET 10 app upgraded to .NET 11
* [ ] Trimming or ahead-of-time compilation
* [ ] More than one server instance, or a proxy in front
* [ ] Hot Reload
* [ ] An IDE as well as the command line
* [ ] Container
* [x] N/A
## Setup
Cookie authentication with one test user, and a reference to the QuickGrid package.
## What to build
A page with a `CacheView` that declares no vary-by dimensions. Test an `AuthorizeView` showing the user name and a `QuickGrid` over a short in-memory list with a sortable column. Repair or remove each failing component before testing the next, or give each case its own page.
In a small class library of your own, add two components: a `` that always refuses to render inside a cache boundary, with no condition that makes it acceptable, and a `` that rerenders live unless the section varies by its price-selection cookie. Give `PricePanel` a lifecycle-generated identifier so live rendering can be distinguished from cache reuse.
Finally, put one `CacheView` inside another.
## Things to try
* Add the `AuthorizeView` with no vary-by configured, read the error, then add `VaryByUser`.
* Add the `QuickGrid` with no vary-by configured, read the error, then vary by the actual sort, direction, and page parameters, or by all query parameters. Sort a column after the page renders.
* Add `` with and without vary-by configured, then move it outside the boundary as the fix for its unconditional refusal.
* Add `` with no vary-by, then with `VaryByCookie`, and check in each case whether it re-renders per request or is served from the entry.
* Nest one `CacheView` in another and read the error.
* Read each message and decide whether you could act on it without opening the source.
## Expected behavior
A component marked to throw refuses with a message naming it and saying what to change. A matching condition can permit caching; an unconditional refusal instead requires moving the component outside the boundary. A rerendering component is different: it can run live without throwing.
### Must hold
* `AuthorizeView` inside a section that does not vary by user throws `InvalidOperationException` naming the component and telling you to vary by user or move it out; adding `VaryByUser` makes the page render.
* `QuickGrid` inside a section that does not vary by query throws a comparable message; adding `VaryByQuery` makes it render, and sorting a column then produces correctly different output.
* `` throws inside the boundary both with and without vary-by configured, and renders when moved outside it.
* `` renders fresh on every request while the section does not vary by cookie, and is served from the entry once it does.
* A nested `CacheView` throws with a message saying nesting is not supported.
### Expected differences between configurations
None expected.
## Evidence to capture
* The verbatim message for each refusal: `AuthorizeView`, `QuickGrid`, `UserBadge`, and the nested section, with the change that resolved it.
* `PricePanel` lifecycle identifiers showing fresh rendering without its cookie condition and cache reuse when the condition is satisfied.
* Whether each refusal message was sufficient to fix the page without opening the source.
## Documentation to use
* [ASP.NET Core Blazor CacheView component](https://learn.microsoft.com/en-us/aspnet/core/blazor/state-management/cacheview-component?view=aspnetcore-11.0)
Report whether the docs explain how a component author declares that their component is unsafe to cache, and how to declare that a vary-by dimension makes it safe. A library author needs both before shipping components that consumers might wrap in a cached section.
## What to report
Report results using the format described in the [validation testing manual](https://github.com/dotnet/aspnetcore/issues/68479). Include link to a repository with the test app.
Contributor guide
Assessment
This issue has not been assessed yet.