How can I restart an app in asp.net core programmatically?
I want to clear cache and cause the application to re-enter the startup.
How can I restart an app in asp.net core programmatically?
I want to clear cache and cause the application to re-enter the startup.
Update: Mirask's answer is more correct for .NET Core 2.
In Program.cs you will see the call to host.Run(). This method has an overload which accepts a System.Threading.CancellationToken. This is what I am doing:
public class Program {
private static CancellationTokenSource cancelTokenSource = new System.Threading.CancellationTokenSource();
public static void Main(string[] args) {
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run(cancelTokenSource.Token);
}
public static void Shutdown() {
cancelTokenSource.Cancel();
}
}
Then, in my Controller I can call Program.Shutdown() and after a few seconds the application dies. If it is behind IIS, another request will automatically start the application.
IApplicationLifetime.ApplicationStopping - it looks like it would be enough to call Cancel on it to start shutdown.IApplicationLifetime.StopApplication(). Do you want to add this as an answer?Before you read my answer: This solution is going to stop the app and cause the application to re-enter the startup in the next request.
.NET Core 2
There may come a time when you wish to force your ASP.Net Core 2 site to recycle programmatically. Even in MVC/WebForms days this wasn't necessarily a recommended practice but alas, there is a way. ASP.Net Core 2 allows for the injection of an IApplicationLifetime object that will let you do a few handy things. First, it will let you register events for Startup, Shutting Down and Shutdown similar to what might have been available via a Global.asax back in the day. But, it also exposes a method to allow you to shutdown the site (without a hack!). You'll need to inject this into your site, then simply call it. Below is an example of a controller with a route that will shutdown a site.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
namespace MySite.Controllers
{
public class WebServicesController : Controller
{
private IApplicationLifetime ApplicationLifetime { get; set; }
public WebServicesController(IApplicationLifetime appLifetime)
{
ApplicationLifetime = appLifetime;
}
public async Task ShutdownSite()
{
ApplicationLifetime.StopApplication();
return "Done";
}
}
}
Source: http://www.blakepell.com/asp-net-core-ability-to-restart-your-site-programatically-updated-for-2-0
ApplicationLifetime.StopApplication(); just stops the application, it doesn't restart itSince the accepted answer is using IApplicationLifetime which became obsolete in ASP.NET Core 3 onwards, the new recommended way is to use IHostApplicationLifetime which is located in the Microsoft.Extensions.Hosting namespace.
In my Blazor application, I can use following code:
@inject IHostApplicationLifetime AppLifetime
<button @onclick="() => AppLifetime.StopApplication()">Restart</button>
For .NET Core 2.2 you can use following code:
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using System.Threading;
namespace BuildMonitor
{
public class Program
{
private static CancellationTokenSource cancelTokenSource = new System.Threading.CancellationTokenSource();
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
host.RunAsync(cancelTokenSource.Token).GetAwaiter().GetResult();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
public static void Shutdown()
{
cancelTokenSource.Cancel();
}
}
}
And server shutdown could be placed for example behind some web page:
using System;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace BuildMonitor.Pages
{
public class StopServerModel : PageModel
{
public void OnGet()
{
Console.WriteLine("Forcing server shutdown.");
Program.Shutdown();
}
}
}
stopServer.bat could be for example like this:
@echo off
rem curl http://localhost:5000/StopServer >nul 2>&1
powershell.exe -Command (new-object System.Net.WebClient).DownloadString('http://localhost:5000/StopServer') >nul
exit /b 0
RunAsync method expects a CancellationToken object instead of CancellationTokenSource, so this code doesn't work for meNone of the solutions above did what I wanted. So that is what I came up with:
public class Program
{
private static CancellationTokenSource cts = new CancellationTokenSource();
private static string[] _args;
private static bool _restartRequest;
public static async Task Main(string[] args)
{
_args = args;
await StartServer();
while (_restartRequest)
{
_restartRequest = false;
Console.WriteLine("Restarting App");
await StartServer();
}
}
public static void Restart()
{
_restartRequest = true;
cts.Cancel();
}
private static async Task StartServer()
{
try
{
cts = new CancellationTokenSource();
await CreateHostBuilder(_args).RunConsoleAsync(cts.Token);
}
catch (OperationCanceledException e)
{
Console.WriteLine(e);
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
If you need this just for a development scenario then you can use dotnet-watch(for dotnet) or dnx-watch(for dnx).
If you want your application to restart in production, then you have to implement something similar to what the watcher does. You need an external process to kill and restart the process. Or you need your app to launch an instance of itself and then kill itself. Unfortunately, there's nothing out of the box for this.
Dotnet 7.0. It's a quick hack when not working behind IIS. Stop the application and get the running process path to restart the process in same terminal window.
public MyController(ILogger<MyController> logger, Microsoft.AspNetCore.Hosting.IApplicationLifetime appLifetime)
{
this.logger = logger;
this.appLifetime = appLifetime;
}
/// <summary>
/// Restarts the API
/// </summary>
[HttpPost("Restart")]
public async Task<int> Restart()
{
appLifetime.StopApplication();
string _currentProcess = Path.GetFullPath(
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
Process.Start(_currentProcess);
return await Task.FromResult(0);
}
IIS will restart the site if it detects the web.config file has changed (by default).
So assuming you can programmatically read and then save that file (you don't even need to make any change), IIS will handle the rest.
This works not just in Blazor (.net core) but also .NET framework (MVC and webforms) and even classic ASP, if you really, really need to.
Probably not the "correct" way, but it is simple and works and given that this has worked for 20+ years, all the way back to classic ASP, it seems pretty robust.
I have put this in old web forms apps for years, used it many times (normally to clear caches) and never had any issue, such as mangling the web.config.