72

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.

4
  • Just to understand better, why do you need this? Commented Mar 21, 2016 at 8:07
  • 5
    I think the most common scenario for me is manipulating settings for the app via some administrative view. The settings are often things initiated on startup. Commented Sep 14, 2016 at 22:36
  • 3
    another usage I can think of is to publish a new version and restart Commented Dec 9, 2017 at 11:39
  • 3
    To clear static cache? This seems like a totally legit requirement to me. Commented Apr 25, 2019 at 19:49

8 Answers 8

39

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.

Sign up to request clarification or add additional context in comments.

8 Comments

This is absolutely perfect, thank you. In regards to handling this when hosted by IIS, this is much better than adding a reference to Microsoft.Web.Administration or tinkering with the web.config file to trick an IIS recycle.
Small update. I found that the method Run(token) no longer is availible to me in .NET Core 2.0. I used the following line to work around this: .RunAsync(cancellationTokenSource.Token).GetAwaiter().GetResult();
Thanks, I was wondering how to do that since the update. You should make this an answer.
@Schwarzie2478, @Chet did you try to use IApplicationLifetime.ApplicationStopping - it looks like it would be enough to call Cancel on it to start shutdown.
I just tested this and you could indeed use IApplicationLifetime.StopApplication(). Do you want to add this as an answer?
|
37

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

4 Comments

I'm doing just like you said but it doesn't shutdown !!
It stops the app but, after the first request the app comes up again. This is just for restarting the application not to shut it down forever.
I tried this, and it stops the application and does NOT restart it (which I kind of expected, based on the method name)
I'm down voting because ApplicationLifetime.StopApplication(); just stops the application, it doesn't restart it
36

ASP.NET Core 3+

Since 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>

3 Comments

Hi @WΩLLE is it possible to do it from the backend ? i tried but it give me an NullReference exception ... maybe i did it wrong... my app is using too much cache and i want to restart the app because of that but dont know how to release the cache by code... is it possible to use your solution?
Ths shuts down the app but the question was how to restart it and that, is not accomplished with this. In fact, I don't even think is possible because once the app is down, it looses the connection with the client, showing an error. Only a new request will restart the app.
@HugoA. Do you want to restart the application and keep all connections alive? This sounds like an impossible requirement.
5

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

2 Comments

RunAsync method expects a CancellationToken object instead of CancellationTokenSource, so this code doesn't work for me
it focuses into token ? cancelTokenSource.Token ?
5

None 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>();
            });
}

1 Comment

I used your code and it works practically. Also I called StopApplication before Restart method. Did you use it in production environment ?
2

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.

1 Comment

It would be a hack, but can the app programmatically change a config file that would trigger an app restart?
2

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);
}

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.