ASP.NET Core In Production – Graceful Shutdown And Reacting To Aborted Requests

In the previous post "ASP.NET Core in production: Take back control of your web app" I mentioned that getting hold if the dependency injection (DI) is just one step of many to improve the architecture of your web applications. Today well will look into 2 other aspects that are best explained together: graceful shutdown and reacting to aborted requests.

In diesem Artikel:

ASP.NET Core In Production – Graceful Shutdown And Reacting To Aborted Requests
Pawel Gerr ist Architekt und Consultant bei Thinktecture. Er hat sich auf .NET Core Backends spezialisiert und kennt Entity Framework von vorne bis hinten.
Image you are in the middle of handling of a web request. How do you know that the WebHost is about to shut down or that the client is not interested in the response anymore? Especially the latter will occur more often and without proper handling you end up wasting resources for nothing.
  1. If your component is interested in server shutdown only then you can inject IApplicationLifetime and use the property ApplicationStopping that is of type CancellationToken. Most of asynchronous operations support cancellation tokens so you just have to pass the token to them but be prepare for handling the OperationCanceledException and TaskCanceledException.
				
					public DemoController(IApplicationLifetime appLifetime)
{
    _appLifetime = appLifetime;
}
    
[HttpGet("MyAction")]
public async Task<IActionResult> MyAction()
{
    CancellationToken token = _appLifetime.ApplicationStopping;
    return await DoSomethingAsync(token);
}
				
			

Having a side-free operation like selecting data from database can be cancelled without much effort just pass the CancellationToken to asynchronous methods (like ToListAsync(token)) or check the property CancellationToken.IsCancellationRequested in case you are iterating over some collection or does other synchronous stuff. However, if the operation is critical, the server is shutting down and the component needs a few seconds more to finish then you can delay the shutdown by registering a callback with the CancellationToken.

Use this feature with care, don’t hold up the shutdown indefinitely!

				
					_appLifetime.ApplicationStopping.Register(() =>
{
    // server is not going to shutdown
    // until the callback is done
});
				
			

Note: you can delay the shutdown by overriding the method Dispose of the controller. Using IDisposable-components to finish some stuff works best if you decouple the DI from ASP.NET life cycle like suggested in my previous post because in most cases you want(!) to shut down the WebHost first so that the endpoints are closed and no new requests can come in. Afterwards you can stop your internal processes and dispose of components.

				
					public class DemoController: Controller
{
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        //finish your stuff synchronously
    }
}
				
			
  1. Being interested in server shutdown only is more of an edge case. Most of the time it doesn’t matter whether the operation has to stop because of the shutdown or because the client has aborted the HTTP request (e.g. by navigating to another page). In both cases you can use HttpContext.RequestAborted which is another CancellationToken. Although it is called „request-aborted“ it is cancelled on shutdown as well because in this case the request is aborted by the server itself not the client.
				
					[HttpGet("MyAction")]
public async Task<IActionResult> MyAction()
{
    CancellationToken token = HttpContext.RequestAborted;
    return await DoSomethingAsync(token);
}
				
			

If the method happens to be an action of an MVC/Web API controller (like in my examples) then you can just specify a new method argument of type CancellationToken to get HttpContext.RequestAborted provided to you.

				
					[HttpGet("MyAction")]
public async Task<IActionResult> MyAction(CancellationToken token)
{
    return await DoSomethingAsync(token);
}
				
			

Want to try it out? I’ve updated the example from my previous post so that you are able to start and abort HTTP requests or restart the WebHost. The sources are available on Github.

Kostenloser
Newsletter

Aktuelle Artikel, Screencasts, Webinare und Interviews unserer Experten für Sie

Verpassen Sie keine Inhalte zu Angular, .NET Core, Blazor, Azure und Kubernetes und melden Sie sich zu unserem kostenlosen monatlichen Dev-Newsletter an.

Diese Artikel könnten Sie interessieren
Unterschiede
.NET
Blazor WebAssembly vs. Blazor Server – Welche Unterschiede gibt es und wann wähle ich was?

Blazor WebAssembly vs. Blazor Server – Welche Unterschiede gibt es und wann wähle ich was?

Das Blazor Framework von Microsoft gibt es inzwischen in drei "Geschmacksrichtungen". Die erste ist Blazor WebAssembly, die zweite Blazor Server, und zu guter Letzt gibt es noch Blazor Hybrid. In diesem Artikel wollen wir uns die zwei "echten", also Browser-basierten, Web-Anwendungs-Szenarien WebAssembly und Server anschauen.
04.07.2022
Three different textured walls
.NET
Dependency Injection Scopes in Blazor

Dependency Injection Scopes in Blazor

The dependency injection system is a big part of how modern ASP.NET Core works internally: It provides a flexible solution for developers to structure their projects, decouple their dependencies, and control the lifetimes of the components within an application. In Blazor - a new part of ASP.NET Core - however, the DI system feels a bit odd, and things seem to work a bit differently than expected. This article will explain why this is not only a feeling but indeed the case in the first place and how to handle the differences in order to not run into problems later on.
31.05.2022
.NET
Asynchrone Operationen: Blazor WebAssembly für Angular-Entwickler – Teil 5 [Screencast]

Asynchrone Operationen: Blazor WebAssembly für Angular-Entwickler – Teil 5 [Screencast]

Eine Webanwendung will natürlich auch mit Daten gefüttert werden. Doch diese müssen irgendwo her kommen. Nichts liegt näher als diese von einer Web API zu laden. Dieser Screencast zeigt, wie asynchrone Operationen in Blazor funktionieren und welche gravierenden Unterschiede es zu Angular gibt.
26.05.2022
.NET
Typings: Blazor WebAssembly für Angular-Entwickler – Teil 4 [Screencast]

Typings: Blazor WebAssembly für Angular-Entwickler – Teil 4 [Screencast]

C# und TypeScript entstammen der Feder der selben Person. Doch sind sie deshalb auch gleich? In diesem Teil der Screencast-Serie erfahren Sie, wie mit Typen in den beiden Programmiersprachen verfahren wird und welche Unterschiede es gibt.
19.05.2022
.NET
Bindings: Blazor WebAssembly für Angular-Entwickler – Teil 3 [Screencast]

Bindings: Blazor WebAssembly für Angular-Entwickler – Teil 3 [Screencast]

Wer Komponenten einsetzt, steht früher oder später vor der Fragestellung, wie man Daten an die Komponente übergibt oder auf Ereignisse einer Komponente reagiert. In diesem Screencast wird gezeigt wie Bindings bei Komponenten funktionieren, also wie eine Komponente Daten von außerhalb benutzen und Rückmeldung bei Aktionen geben kann.
12.05.2022
.NET
Komponenten: Blazor WebAssembly für Angular-Entwickler – Teil 2 [Screencast]

Komponenten: Blazor WebAssembly für Angular-Entwickler – Teil 2 [Screencast]

Bei der Entwicklung einer Webapplikation kommt es ständig vor, dass UI-Teile immer und immer wieder verwendet werden. Damit nicht immer Copy & Paste verwendet werden muss, können diese Teile in Komponenten zusammengefasst werden.
05.05.2022