dotnet / dotnet/aspnetcore

[Validation] Components that refuse to be cached in CacheView

Open
#69,125 0 comments 0 reactions 1 assignee Claimed by @BrundhaVelusamy View on GitHub
area-blazor Validation validation-scenario
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.