> ## Content Index
> Fetch the complete content index at: https://devinside.cloud/llms.txt
> Use this file to discover other available public pages before exploring further.

# Blazor Interfaces for Slow, Fallible AI
- URL: https://devinside.cloud/blazor-interfaces-for-slow-fallible-ai/
- Published: 2026-04-10T11:30:00.000Z
- Updated: 2026-11-12T17:08:29.000Z
- Description: An AI interface can be technically responsive and still be dishonest. It can animate a progress bar while nothing measurable is progressing. It can display “cancelled” while a server continues working. It can replace a current answer with a late result from a previous request.
- Author: Marcin Borecki
- Tags: Engineering, Microsoft AI Engineering, #m22, #devinside-review

START WITH THE MECHANISM

Interactive companion and laboratory update: 12 November 2026\. The editorial date places the topic on the timeline; this current explanation and its measured evidence retain their actual preparation and execution dates.

THE FULL INVESTIGATION

## Blazor Interfaces for Slow, Fallible AI

Editorial context: 10 April 2026 · Prepared and updated: 12 November 2026

Dates and technology context

This is a retrospective editorial timeline. Topic context: 10 April 2026\. First publicly available: 12 November 2026\. Current text, visuals and laboratory revisions were prepared on 12 November 2026.

The real Blazor circuit and browser checks use SDK10.0.400/runtime10.0.15, executed November2026\. April2026 contains only the earlier interaction contract and .NET10.0.100/10.0.0 baseline.

An AI interface can be technically responsive and still be dishonest. It can animate a progress bar while nothing measurable is progressing. It can display “cancelled” while a server continues working. It can replace a current answer with a late result from a previous request.

These failures are not primarily about styling. They come from an incomplete model of the operation. A slow, fallible AI task needs an interface that can express uncertainty, preserve user intent and recover after interruption. Blazor supplies the component model; the application must supply the truth about what is happening.

Consider an assistant that analyzes a document and produces a structured recommendation. Uploading, validating, retrieving evidence, calling a model and checking the result are different stages. A useful interface tells the user which stage has been reached without claiming more certainty than the backend can provide.

The examples target the established component and asynchronous programming model in Blazor on .NET 10\. They are illustrative fragments, not a complete application or an executed accessibility test. The platform release establishes the version baseline. [Microsoft .NET 10 announcement](https://devblogs.microsoft.com/dotnet/announcing-dotnet-10/?ref=devinside.cloud).

## Model states before designing the screen

Begin with a state machine that distinguishes idle, submitted, running, cancellation requested, cancelled, succeeded, failed and outcome unknown. Some applications need fewer states, but collapsing them should be a deliberate decision.

“Submitted” means the client sent a request. “Accepted” means the server durably owns it. “Running” means execution has started. These events can happen at different times, and a disconnected browser may observe only some of them.

An unknown outcome is especially important when the task can create effects. If the connection fails after the server commits a result, the client cannot conclude that the task failed. The appropriate next action is to look up the operation, not to offer an unconditional “try again” button that creates duplicate work.

Keep user intent separate from server outcome. Clicking Cancel records a request to stop. It does not prove that all in-flight work stopped. The UI should display a pending cancellation state until the server confirms the terminal outcome or explains why part of the operation already completed.

## Do not invent a percentage

A progress bar is meaningful when the denominator is known and the completed work is comparable. Processing 40 of 100 similarly sized files can support a count-based indicator. Waiting for a model response generally cannot support an honest claim that the work is 73 percent complete.

Use stage descriptions and elapsed time when the total work is unknown. “Retrieving source material” or “Checking the response” is more useful than a smoothly advancing number that stalls at 99 percent. If a stage can legitimately repeat, say so instead of making the repetition look like the application has gone backward.

Estimated time can be helpful, but label it as an estimate and explain the basis when it matters. A rolling average from previous operations is not a guarantee for this operation. Large documents, cold dependencies and retries can produce very different durations.

The interface should also avoid implying that streamed text is a final answer. A model may emit a plausible opening and later encounter missing evidence. If the product validates the complete output, distinguish draft streaming content from an accepted result. The user should know which content is safe to copy or act on.

## Give each operation an identity and a revision

01 / See the idea

### Intent and outcome are different states

![A UI state machine separates submission, server ownership, running, cancellation and terminal outcomes.](https://devinside.cloud/content/images/2026/11/devinside/M22-v1.svg)

[Enlarge diagram](https://devinside.cloud/content/images/2026/11/devinside/M22-v1.svg)

A hypothetical document analysis is submitted before the server accepts it. A later cancel click expresses intent, while the terminal result must still come from the operation record.

Interpretation and evidence
- Submitted is not accepted.
- Cancel requested is not cancelled.
- Unknown requires a lookup.
conceptual/hypothetical, not measured

Asynchronous updates can arrive late, out of order or after the user starts another task. A component should not treat the last callback to run as the authoritative state.

Use an operation identifier and an increasing server-side revision or event sequence. Apply an update only if it belongs to the current operation and is newer than the state already displayed. This is a small rule with a large effect on UI correctness.

```csharp
// Application-owned state. Illustrative, not executed.
public sealed record OperationView(
    Guid OperationId,
    long Revision,
    string Stage,
    string Status,
    string? ResultReference);

private OperationView? current;

private void Apply(OperationView update)
{
    if (current is not null &&
        (update.OperationId != current.OperationId ||
         update.Revision <= current.Revision))
        return;

    current = update;
}

```

The complete component must establish `current` when it starts a new operation. Otherwise an unsolicited first update could become the current one. Server revisions should reflect durable operation state, not a local counter that resets whenever a worker restarts.

This rule protects the display from stale information. It does not authorize access to an operation. Every server endpoint that returns state or results must independently verify that the caller may read them.

## Respect the component's asynchronous lifetime

Blazor's synchronization context does not make every asynchronous method atomic. A component can be re-entered when it awaits incomplete work, and lifecycle events can occur while an earlier operation is still in progress. Microsoft's guidance explicitly discusses this re-entrancy and the need to leave the component in a valid state before awaiting. [Blazor synchronization context](https://learn.microsoft.com/en-us/aspnet/core/blazor/components/synchronization-context?view=aspnetcore-10.0&ref=devinside.cloud).

Set the state that the renderer needs before starting an await. Keep references to owned cancellation sources and subscriptions. When a callback comes from outside the normal component event flow, marshal the state update through `InvokeAsync` rather than assuming it is running in the correct context.

```csharp
// Fragment for updates raised by an external subscription.
private Task OnOperationUpdateAsync(OperationView update) =>
    InvokeAsync(() =>
    {
        if (disposed)
            return;

        Apply(update);
        StateHasChanged();
    });

```

`disposed` is component-owned state, and the subscription must be detached during disposal. This fragment is not sufficient on its own: the owner still needs to observe callback failures and close the subscription. The purpose is to show that renderer access and operation identity are separate checks.

Do not call `StateHasChanged` blindly during disposal. A component being removed has a different lifecycle from one displaying a new result. Microsoft's disposal guidance cautions against relying on exact disposal timing and against assuming asynchronous initialization has completed. [Razor component disposal](https://learn.microsoft.com/en-us/aspnet/core/blazor/components/component-disposal?view=aspnetcore-10.0&ref=devinside.cloud).

## Cancellation needs a server contract

02 / A concrete example

### Late messages must not overwrite today

![A hypothetical update table accepts only the current operation and a newer revision.](https://devinside.cloud/content/images/2026/11/devinside/M22-v2.svg)

[Enlarge diagram](https://devinside.cloud/content/images/2026/11/devinside/M22-v2.svg)

The display is showing operation B at revision 3\. An update for A at revision 9 and B at revision 2 are ignored; B at revision 4 is accepted.

Interpretation and evidence
- Match the operation ID first.
- Reject equal or older revisions.
- State authority remains on the server.
conceptual/hypothetical, not measured

Cancelling a client-side wait can improve responsiveness, but it does not necessarily cancel server work. An HTTP request abort, an operation cancellation endpoint and a model provider's cancellation behavior are different mechanisms.

For a durable job, expose cancellation as an authenticated command against the operation identifier. The command should be idempotent and return the state the server knows. If the task is already complete, return that result rather than pretending the cancellation rewound it.

A component can stop listening immediately when the user navigates away while allowing the server-owned job to continue. That may be the right product behavior. Alternatively, leaving the page may request cancellation. Either choice is defensible if it is explicit. Surprise background work and surprise loss of work are both poor defaults.

The UI should explain the scope: “Stop waiting” is different from “Request cancellation.” If some results have already been committed, report partial completion. A single red toast saying “Cancelled” can conceal a complicated and important state transition.

## Recovery starts with a durable operation record

If the operation exists only in component memory, reconnecting to the application creates a mystery. The browser knows it was waiting, but the server may have finished, failed or restarted.

Use a durable operation record for work that must outlive the connection. It should include the actor or tenant scope, submitted input reference, current state, revision, timestamps and any result reference. The browser can then reconnect and request the latest state.

Do not persist sensitive document content in browser storage merely to make reconnection easy. A small operation identifier may be sufficient. Even that identifier should not function as a bearer credential; possession of it must not bypass authorization.

On recovery, show what is known and what is being reconciled. “We are checking the result of your previous request” is more accurate than silently launching another run. A good recovery experience reduces duplicate submissions because the application can account for its own work.

## Make status understandable without animation

03 / Watch the mechanism

### Cancellation cannot rewind a commit

![A server commit can win a race against a browser cancellation request.](https://devinside.cloud/content/images/2026/11/devinside/M22-v3.svg)

Cancellation cannot rewind a commitA server commit can win a race against a browser cancellation request.M22-V3 / TECHNICAL EXPLANATIONCancellation cannot rewind a commitConceptual / hypothetical example. Not measured results.BrowserServerCommit result R7Cancel requestedcancelShow completed

Play animation[Enlarge diagram](https://devinside.cloud/content/images/2026/11/devinside/M22-v3.svg)

Static view. Play to see how the mechanism unfolds.

In this hypothetical race, the server commits result R7 before receiving Cancel. The browser first shows cancellation requested, then the confirmed completed state rather than a false cancelled label.

Interpretation and evidence
- Show the pending request honestly.
- Keep status outside the busy region.
- Use the confirmed terminal outcome.
conceptual/hypothetical, not measured

A spinner communicates activity visually, but it does not necessarily communicate meaning. Use a text status that remains understandable to assistive technology and to a person who has stepped away and returned.

In a Razor component, a small status region can announce meaningful transitions. Avoid announcing every token or every tiny progress event, which can overwhelm the user. Announce stage changes, completion, cancellation and actionable failures.

```razor
@* Illustrative markup; accessibility testing not performed. *@
<p role="status" aria-live="polite">@StatusMessage</p>
<section aria-busy="@(IsRunning ? "true" : "false")">

    <button type="button"
            disabled="@(!CanRequestCancellation)"
            @onclick="RequestCancellationAsync">
        Request cancellation
    </button>
</section>

```

Keep the status region outside the busy result container. Assistive technology may defer changes owned by an element while its `aria-busy` value is true, so placing stage announcements inside that element can defeat the intended feedback. The result region can remain busy while its separate status announces meaningful transitions. [WAI-ARIA 1.2, aria-busy](https://www.w3.org/TR/2023/REC-wai-aria-1.2-20230606/?ref=devinside.cloud#aria-busy).

The W3C status-message criterion explains why important updates should be programmatically available without forcing focus changes. Markup is only part of that work: test actual announcements, keyboard navigation, focus placement and error recovery with the chosen UI. [W3C guidance on status messages](https://www.w3.org/WAI/WCAG21/Understanding/status-messages.html?ref=devinside.cloud).

Keep controls stable where possible. If a button disappears and a new result region appears, focus may end up in a confusing place. Decide where focus should go after submission, cancellation and completion, and verify the behavior rather than assuming the browser will make a sensible choice.

## Design failure messages around the next decision

“Something went wrong” is sometimes the only safe public message, but it rarely tells the user what to do. Distinguish an invalid document, insufficient evidence, a temporary dependency failure and an unknown outcome.

For an invalid document, explain the input requirement. For insufficient evidence, offer clarification or a way to provide the missing source. For a temporary failure, say whether retry is safe and whether the previous operation is definitely terminal. For an unknown outcome, begin reconciliation.

Do not expose raw model or infrastructure errors. They can contain internal details and may be misleading outside their original context. Map them into a stable application error contract while keeping a correlation identifier for support.

Also preserve the user's work. A long-running request should not erase a carefully written prompt merely because a dependency timed out. Retain the input locally only under an appropriate data policy, and allow the user to revise it without accidentally mutating a running operation's recorded input.

## Test time and disorder, not only content

Build a fake operation service that can emit updates in a controlled order. Test a delayed completion from operation A after operation B has started. Test duplicated revisions, a disconnected stream, a cancellation race and a terminal result arriving after the cancellation request.

Test component removal during every await boundary that owns resources. Verify that subscriptions close, callbacks do not update disposed components and exceptions are observed. A test that only checks the final answer text misses the lifecycle in which most of these bugs live.

For usability, observe people completing the task under realistic delays. Ask what they believe the system is doing, whether they think cancellation has taken effect and whether they know a result is final. A technically correct state model can still be communicated badly.

No runtime or user testing has been performed for this manuscript. The proposed tests are an acceptance plan. A later implementation should retain actual results from component tests, reconnect scenarios and assistive-technology checks rather than promoting the presence of ARIA attributes into an accessibility claim.

## The interface should help the user remain in control

Slow AI does not require pretending that uncertainty has disappeared. It requires communicating uncertainty in a way that supports action. A clear stage, a truthful cancellation state and a recoverable operation record can create more confidence than an elaborate animation.

The engineering objective is to preserve a coherent relationship between user intent, server responsibility and visible outcome. Blazor can express that relationship cleanly, but it cannot invent it. Once the state model is honest, the interface can be calm even when the operation is not fast.

## A later Blazor application makes the interaction observable

*Implementation note, prepared 12 November 2026\. The original April 2026 sections describe the interaction contract. The application below is a later implementation using SDK 10.0.400 and runtime 10.0.15; it is not evidence of execution at the earlier contextual date.*

The small Blazor application accompanying this article turns the central states into observable behavior. It has a request field, a choice of scripted provider behavior, start and cancellation controls, a result region and an explicit status message. It does not call a hosted AI service.

The provider is deliberately controlled by the local interface. A release button completes a pending operation. Another button releases the oldest pending operation, even when a newer request is already displayed. This lets the browser test produce the important ordering directly rather than hoping a sleep is long enough to create a race.

The application runs as interactive server-side Blazor on a temporary loopback address. The test wrapper starts it, discovers its assigned port, uses one browser page and closes both browser and server afterward. It is a functional demonstration, not a deployed service or a latency benchmark.

The absence of a real model is a precise limitation, not a hidden substitution. This experiment tests the interface's response to a provider contract: waiting, completion, cancellation and failure. Model quality, remote network behavior and provider-specific streaming require separate evidence.

## The view state belongs to one operation

01 / Watch the mechanism

### A late result must pass the identity gate

![A completion carrying the current operation identity may update the result; an older identity is ignored after await.](https://devinside.cloud/content/images/2026/11/devinside/M22-ui-1.svg)

A late result must pass the identity gateM22 / LIVE UI CONTRACTA late result must pass the identity gateCompletion arrivesCarries operation IDCurrent identity?Compare after awaitSame operationApply current resultOlder operationIgnore stale resultThe test releases the old response after the new result is visible.

Play animation[Enlarge diagram](https://devinside.cloud/content/images/2026/11/devinside/M22-ui-1.svg)

Static view. Play to see how the mechanism unfolds.

The browser test completes the second request first, then deliberately releases the older request. The old response cannot change the current result, identity or revision.

Interpretation and evidence
- Check identity after the awaited operation.
- A new request does not prove the old provider stopped.
- Test a stale response by making it arrive.
Executed scripted-provider browser checks; no hosted model.

The implemented state record carries an operation identity and a revision alongside the visible state:

```csharp
public sealed record OperationState(
    Guid Id, long Revision, string Status,
    bool Busy, string Result, string Prompt);

```

Starting a request creates a new identity, resets its local revision to one and enters Waiting. The result is empty until the current operation produces an accepted completion. A second request replaces the displayed operation immediately and requests cancellation of the earlier one.

Replacement is not proof that the earlier provider stopped. The older operation may still finish, especially in the deliberately uncooperative fixture mode. Its continuation therefore checks identity before changing the visible state:

```csharp
private bool IsCurrent(Guid id) => !disposed && state.Id == id;

```

The check is repeated after the provider's awaited operation finishes. If the result belongs to an older request, it is ignored for display. The fixture increments a diagnostic count so the browser test can establish that the late completion really occurred, rather than simply failing to arrive during the test.

The revision is local to the current operation. It advances when cancellation is requested or a terminal outcome is accepted. The implementation has one final provider response per operation; it does not claim to implement a general streamed-event protocol with arbitrary within-operation reordering. The earlier revision-filtering discussion identifies the additional contract such a protocol would need.

This distinction keeps the example honest. A request identity protects against one class of stale update. It does not, by itself, solve every ordering problem inside a long-running operation.

## Cancellation has an observed state and a requested state

The cancellation control first changes the status to CancelRequested and signals the operation's cancellation source. It does not immediately claim that the provider has stopped.

In cooperative mode, the scripted provider connects that token to its pending completion source. The awaited operation then ends with cancellation, and the component enters Cancelled with no accepted result.

In late-response mode, the provider intentionally ignores cancellation. The interface continues to report that cancellation has been requested and that it is waiting for the provider to finish or acknowledge the request. When the scripted result eventually arrives, the component checks the current token and declines to accept the result as successful.

This behavior is appropriate for the demonstration because the provider has no external effects. A real operation that writes data or sends an instruction would need a richer contract. Declining to display its result would not undo the effect. The interface would need to report and reconcile what actually happened.

The same care applies to supersession. Starting another request is a decision about which result the user currently wants to see. It does not erase the earlier operation's possible obligations. In this fixture, there are no remote obligations, so cancelling and ignoring stale display updates is enough for the stated boundary.

The test should make that scope visible. It verifies display correctness under cooperative and uncooperative completion. It does not certify cancellation semantics for a particular AI provider, storage system or business action.

## An await does not freeze the component

Blazor's synchronization context provides a single logical execution context within a server-side circuit, but an incomplete await allows the component's control flow to be re-entered. Another event or disposal can occur before the original operation resumes. Microsoft documents this distinction explicitly. [Blazor synchronization context](https://learn.microsoft.com/en-us/aspnet/core/blazor/components/synchronization-context?view=aspnetcore-10.0&ref=devinside.cloud).

The implementation therefore sets a valid Waiting state before awaiting the provider. It captures the request text, provider mode and operation identity into local variables. Later edits to the input do not silently change what the in-flight operation means.

The continuation checks both disposal and identity before applying an outcome. The cancellation source belongs to that invocation and is disposed in its own `finally` block. It clears the component's current cancellation reference only if that reference still points to the same source. Otherwise an old operation could accidentally remove the cancellation handle for the new one.

These details are small but consequential. The code is managing several overlapping lifetimes: the component, the displayed request, an earlier provider operation and the cancellation objects associated with each attempt. A single boolean called loading would not express all of them.

The provider service is scoped to the circuit and uses completion sources to gate responses. Component disposal cancels pending fixture work. This is not a durable operation store; a circuit disappearing does not leave an operation that another browser can recover. That remains a separate feature from the state-correlation behavior demonstrated here.

## Put the status outside the busy result region

02 / See the idea

### Status remains outside the busy result region

![The live status is a sibling of the busy result region, not a descendant.](https://devinside.cloud/content/images/2026/11/devinside/M22-ui-2.svg)

[Enlarge diagram](https://devinside.cloud/content/images/2026/11/devinside/M22-ui-2.svg)

The status message explains waiting while the result region is marked busy. The test checks that the live status has no aria-busy ancestor and that no percentage is fabricated.

Interpretation and evidence
- Keep status announcements outside the busy result region.
- Describe the known state rather than inventing progress.
- Separate DOM checks from actual assistive-technology testing.
Executed DOM assertions and visible real UI states.

The status message is a sibling of the result region. It has `role="status"`, explicit polite live-region behavior and `aria-atomic="true"`. The result region carries `aria-busy` while the current operation is waiting.

```html
<p id="status" role="status" aria-live="polite" aria-atomic="true">
    Current operation status
</p>
<div id="result-region" aria-busy="true">
    Result content
</div>

```

The separation is intentional. The message describing the wait is not placed inside the region whose updates are being marked busy. The browser test checks this structural relationship rather than merely searching for an `aria-live` attribute somewhere on the page.

W3C's status-message technique explains the use of the status role to convey updates without moving focus and notes the value of explicit atomic behavior. This supports the markup choice; it does not mean that an automated DOM check proves the experience of every screen-reader and browser combination. [W3C ARIA22](https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA22?ref=devinside.cloud).

The text describes states, not fabricated percentages. Waiting says that no completion estimate is available. CancelRequested says that the application is still waiting for completion or acknowledgement. Failed names the next available action, while Completed states that the displayed result belongs to the current request.

The controls also remain usable while work is pending. The user can request cancellation or start another request. That is a deliberate interaction contract, and the identity checks make its consequence safe within this local example.

## Test the late result by making it arrive

The browser scenario starts a first request in the mode that ignores cancellation. It then starts a second request, verifies that the operation identity changed and releases the current operation. The second result becomes visible.

Only then does the test release the oldest pending operation. The stale-completion counter must increase, while the displayed result, current identity and revision remain unchanged. This is stronger evidence than waiting briefly and observing that the second result is still present. The test establishes that the late result was actually processed and rejected for display.

The cancellation scenarios use the same principle. Cooperative cancellation must reach Cancelled. Uncooperative cancellation must remain visibly pending until the test releases the provider, after which the result is not accepted as successful.

Failure and retry are separate. The fail-once mode raises a controlled error before returning a result. The interface exposes Retry and leaves the result region non-busy. Retrying creates a new operation identity; releasing that new operation then supplies a successful result. The fixture does not imply that every real failure is safe to retry automatically.

The wrapper also verifies a narrow mobile condition: at a 390-pixel viewport, the document does not overflow horizontally. It captures real waiting, completed and mobile-error states for review. These images document an executed interface, not a generated mockup or a claim about model behavior.

## The page must become interactive before a test can count

A server-rendered page can look complete before the interactive circuit is ready. Testing an early click without establishing that boundary can produce a misleading result: the button exists, but the application has not yet attached the behavior under examination.

The reference page exposes a small diagnostic marker after its first interactive render. The test waits for that marker before starting a request. The marker is not a user-facing progress estimate; it identifies a test precondition.

During implementation, the first browser attempts rendered the page but did not reach interactivity because the framework's static asset was not mapped correctly. Those attempts were not counted as successful UI tests. Correcting asset delivery and waiting for the actual interactive boundary are part of making the evidence credible.

This is a useful reminder for application testing in general. An HTTP success response, visible markup and an attached interaction are different observations. The test should establish the one its claim requires.

The completed demonstration remains deliberately small. It has no authentication system, persisted conversation, network reconnect recovery or streaming partial-answer protocol. Its value is a runnable, inspectable implementation of the state boundaries that a more complete application would need to preserve.

## The executed browser checks and captured states

The final browser run passed nine named functional groups with no reported page or resource errors. It checked waiting, the placement of the live status, absence of fabricated percentage progress, cooperative cancellation, supersession, a deliberately released stale completion, uncooperative cancellation, failure and retry, and the narrow mobile overflow condition. These are grouped behavioral checks, not nine claims of general accessibility compliance.

The waiting capture shows an actual pending scripted operation. Its result area is busy while the status explains that no completion estimate is available.

![Actual Blazor waiting state with request controls, an external status message and no accepted result.](https://devinside.cloud/content/images/2026/11/devinside/M22-ui-waiting.png)

The completed capture was taken after the second request finished and the earlier request was deliberately released. The displayed answer remains attached to the second request; the ignored-stale-completion count records that the first result did arrive.

![Actual Blazor completed state showing the second request's result after one stale completion was ignored.](https://devinside.cloud/content/images/2026/11/devinside/M22-ui-completed.png)

The mobile capture records the controlled error state before retry. The test subsequently retried with a new operation identity and accepted the released result.

![Actual mobile Blazor error state with an available retry action and a non-busy result region.](https://devinside.cloud/content/images/2026/11/devinside/M22-ui-error-mobile.png)

The test wrapper closed its browser and stopped the temporary Kestrel process, which exited successfully. No timing benchmark or hosted model call was performed. Screen-reader behavior was not manually evaluated; the executed accessibility-related checks concern DOM semantics and layout. That boundary should remain visible when these screenshots are reused in a presentation or portfolio.

Historical versions and verification boundaries

These pins existed before the context date. Availability and static API checks do not establish a successful build or a production-safe patch level. Execution claims are limited to explicitly identified companion checks.

| Component                     | Version  | Available by | Source                                                                                                                   |
| ----------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------------------------------------ |
| .NET SDK                      | 10.0.100 | 2025-11-11   | [Primary record](https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/10.0/releases.json?ref=devinside.cloud) |
| .NET runtime                  | 10.0.0   | 2025-11-11   | [Primary record](https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/10.0/releases.json?ref=devinside.cloud) |
| ASP.NET Core shared framework | 10.0.0   | 2025-11-11   | [Primary record](https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/10.0/releases.json?ref=devinside.cloud) |
| C#                            | 12.0     | 2024-12-03   | [Primary record](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12?ref=devinside.cloud)                |

[Download the complete laboratory and execution records](https://devinside.cloud/content/files/2026/11/M22-lab.zip).