In self-hosted OWIN Web API, how to run code at shutdown?
Asked Answered
A

3

45

I am self-hosting a OWIN Web API using these code snippets:

class Startup
{
    public void Configuration(IAppBuilder appBuilder)
    {
        var config = new HttpConfiguration();
        var route = config.Routes.MapHttpRoute("DefaultApi", "{controller}");
        appBuilder.UseWebApi(config);
    }
}

WebApp.Start<Startup>("http://localhost:8080")

I would like to run some code when my Web API service shuts down. I'm looking for something like HttpApplication.Application_End, a Disposed event, or a well-placed override void Dispose().

How do I run code when the Web API service shuts down?

Adkison answered 27/4, 2014 at 0:14 Comment(0)
F
61

This can be achieved by getting the host's cancelation token and registering a callback with it like so

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var context = new OwinContext(app.Properties);
        var token = context.Get<CancellationToken>("host.OnAppDisposing");
        if (token != CancellationToken.None)
        {
            token.Register(() =>
            {
                // code to run
            });
        }
    }
}

I was told by someone on the Katana team that this key is for host specific functionality and therefore may not exist on all hosts. Microsoft.Owin.Host.SystemWeb does implement this, but I'm not sure about the others.

The easiest way to verify if this will work for you is to check app.Properties for the host.OnAppDisposing key.

Forest answered 27/4, 2014 at 4:11 Comment(4)
@Wally: It would be great if you explain how to test it.Antibiotic
To test it, dispose the result of the WebApp<Startup>() call and watch the code in the token.Register() action execute..Upgrade
The if (token != CancellationToken.None) is a little redundant, CancellationToken.None.Register(action) does the check and returns an empty CancellationTokenRegistration() for non-cancellable tokens. You can do a one-liner: new AppProperties(app.Properties).OnAppDisposing.Register(() => { /* stuff */ });Upgrade
You are such a ninja!Willawillabella
D
70

I think there is a better way to get the CancellationToken:

var properties = new AppProperties(app.Properties);
CancellationToken token = properties.OnAppDisposing;

AppProperties is under namespace Microsoft.Owin.BuilderProperties, which comes from this nuget package: http://www.nuget.org/packages/Microsoft.Owin/

The description of property OnAppDisposing says:

Gets or sets the cancellation token for “host.OnAppDisposing”.

Please refer to: http://msdn.microsoft.com/en-us/library/microsoft.owin.builderproperties.appproperties%28v=vs.113%29.aspx

Desirable answered 23/9, 2014 at 3:36 Comment(2)
What do you do with the instance of properties?Sweltering
You can throw it away, it is just a wrapper around app.Properties.Airwoman
F
61

This can be achieved by getting the host's cancelation token and registering a callback with it like so

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var context = new OwinContext(app.Properties);
        var token = context.Get<CancellationToken>("host.OnAppDisposing");
        if (token != CancellationToken.None)
        {
            token.Register(() =>
            {
                // code to run
            });
        }
    }
}

I was told by someone on the Katana team that this key is for host specific functionality and therefore may not exist on all hosts. Microsoft.Owin.Host.SystemWeb does implement this, but I'm not sure about the others.

The easiest way to verify if this will work for you is to check app.Properties for the host.OnAppDisposing key.

Forest answered 27/4, 2014 at 4:11 Comment(4)
@Wally: It would be great if you explain how to test it.Antibiotic
To test it, dispose the result of the WebApp<Startup>() call and watch the code in the token.Register() action execute..Upgrade
The if (token != CancellationToken.None) is a little redundant, CancellationToken.None.Register(action) does the check and returns an empty CancellationTokenRegistration() for non-cancellable tokens. You can do a one-liner: new AppProperties(app.Properties).OnAppDisposing.Register(() => { /* stuff */ });Upgrade
You are such a ninja!Willawillabella
R
2

This is the same as arthas's answer but I've made it into an extension method

public static IAppBuilder RegisterShutdown(this IAppBuilder app, Action callback)
{
    if (app == null)
    {
        throw new ArgumentNullException(nameof(app));
    }

    var properties = new AppProperties(app.Properties);
    var token = properties.OnAppDisposing;

    if (token != CancellationToken.None)
    {
        token.Register(callback);
    }

    return app;
}

Because then you can easily register shutdown actions like this

app.RegisterShutdown(() => Serilog.Log.CloseAndFlush());
Rattletrap answered 28/8, 2022 at 0:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.