dotnet / dotnet/aspnetcore

Blazor Server CancellationToken attached to circuit

Open
#66,660 2 comments 1 reaction 0 assignees View on GitHub
area-blazor feature-request
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 10h
Merged PRs (30d)
281

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Is your feature request related to a problem? Please describe the problem.

What I'm trying to achieve is the same that we can achieve by using `HttpContext.RequestAborted`, it would be good if we can cancel any operation that is "already lost" due to disconnection ou user intentional disconnect at Blazor Server.

Couldn't find a built-in implementation or any examples at Microsoft documentation.

### Describe the solution you'd like

The idea behind it is to have the same behavior of `HttpContext.RequestAborted`.
An api that we can rely once there is some kind of disconnection by providing a cancellation token that we can use at the blazor components.

> Maybe some kind of `Circuit.Current.IsCancellationRequested` thing.

Since this is usually a common "built-in feature", such as the ones provided in HttpContext, Background Services, it would be nice to have one attached to Blazor Server Circuit.

Would be also good to have it linked to a global CancellationTokenSource of the app _(such as the ones that we rely on `BackgroundService`/`IHostedService`)_ that cancels all connected circuits.

### Additional context

A simple solution could be done using a scoped circuit handler. But not as good as I would like to be.

Since there are two main events: a lost of connection and full disconnect (aka down). I had to do some workaround to handle both, when there connection is lost it keeps the scoped `CircuitConnectionState` instance however, at this point I should cancel any running operation because the user has already "lost the request" and it will be a waste of resource until it reconnects:

```csharp
public class CircuitConnectionState
{
private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();

public CancellationToken CancellationToken => _cancellationTokenSource.Token;

public void Reconnected()
{
if (_cancellationTokenSource.IsCancellationRequested)
{
_cancellationTokenSource.Dispose();
_cancellationTokenSource = new CancellationTokenSource();
}
}

public void Disconnected()
{
_cancellationTokenSource.Cancel();
}
}
```

```csharp
public class CancellationCircuitHandler : CircuitHandler
{
private readonly CircuitConnectionState _state;

public CancellationCircuitHandler(CircuitConnectionState state)
{
_state = state;
}

public override Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken)
{
_state.Reconnected(); //Should be useless
return base.OnCircuitOpenedAsync(circuit, cancellationToken);
}

public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
{
_state.Reconnected();
return base.OnConnectionUpAsync(circuit, cancellationToken);
}

public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken)
{
_state.Disconnected();
return base.OnConnectionDownAsync(circuit, cancellationToken);
}

public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken)
{
_state.Disconnected();
return base.OnCircuitClosedAsync(circuit, cancellationToken);
}
}
```

DI at `Program.cs`:
```
builder.Services.AddScoped();
builder.Services.AddScoped();
```

If there is any other suggestion or a better implementation, please share.

Contributor guide

Open the contributing guide

Research direction

Start by reading the CircuitHandler lifecycle methods named in the issue, especially OnConnectionDownAsync, OnConnectionUpAsync, and OnCircuitClosedAsync. Review the Program.cs registrations and the CancellationCircuitHandler and CircuitConnectionState workaround. Done means an agreed built-in cancellation API addresses connection loss, reconnection, circuit closure, and the proposed app-wide cancellation behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
api, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.