Bruno Grieder
Bruno Grieder

Reputation: 29834

.NET hot deploy/undeploy of bundled code. How to? Which container?

We are new to the .NET world and have built a small C# application on top of Nancy

We are looking for a way to "package" the application code so that we can programmatically hot deploy and undeploy it on top of a minimal Nancy based container (or any other appropriate container you may suggest)

How do we do this in the .NET world ?

In the JVM world, one way to do it is to package a Web Application Resource (war) that is deployed on top of a servlet engine, typically Jetty or Tomcat. There are other solutions (micro-containers, using class loaders directly, etc..). We are looking of an equivalent .NET paradigm.

EDIT Dec 5

There seems to be solutions around building Assemblies and using methods such as Assembly.LoadFromString.

This still seems pretty manual and we are looking for a C# library/framework to help with loading/unloading

Upvotes: 0

Views: 517

Answers (4)

Nerlog
Nerlog

Reputation: 261

Unfortunately, it's not a typical task in .NET world, so you won't necessarily find a simple widely used plug-ins solution.

There is Managed Extensibility Framework, later known as Microsoft.Composition, later known as System.Composition. Please check How to discover new MEF parts while the application is running? as it may be a solution you are looking for.

There are some articles on using System.Composition with .NET Core as well.

It's not hard to implement a plugin system yourself though using an IoC framework like AutoFac .

Let's assume your application has Nancy modules which do call services, and the services implement the actual logic you may want to change dynamically. That makes a service essentially a plugin. The idea is to make IoC to return an updated instance of a service for every http call.

  1. You could have a scoped service provider \ factory which will resolve and create a service instance from a refreshed assembly using reflection.
  2. You could refresh services collection container (or create a new IoC container) on assembly reload.

Sadly, in both cases you will have to manually detect an assembly file changed, but this is a trivial job with FileSystemWatcher class.

Also, in some IoC libraries updating dependencies in runtime is not considered a good practice, take a look here, for example.

Upvotes: 1

Evk
Evk

Reputation: 101523

You can load your code into separate AppDomain and use shadow copying for hot reload. Suppose you have nancy application like this:

static void Main(string[] args) {
    using (var host = new NancyHost(new Uri("http://localhost:34455"))) {
        host.Start();
        Console.WriteLine("started");
        Console.ReadKey();
    }
}

public class SampleModule : Nancy.NancyModule {
    public SampleModule() {
        Get["/"] = _ => "Hello World!";
    }
}

And you want to be able to update it without restarting hosting process. You can do it like this (warning - non-production ready code, just sample). Create another application like this:

static void Main() {
    while (true) {
        var setup = new AppDomainSetup();
        setup.ApplicationBase = @"Path to directory with your nancy app";
        setup.ShadowCopyFiles = "true";
        var domain = AppDomain.CreateDomain("Nancy", new Evidence(), setup); 
        domain.ExecuteAssembly(@"Path to your nancy app exe");
        AppDomain.Unload(domain);
    }
}

Then start your second (host) application. It will create new app domain and start your nancy application in it. Now you can update your nancy application while host application is running (right in that folder - because of shadow copying, files are not locked). To apply updates - press any key in host application. This will tear down app domain with your old version and create new app domain with new version, without restarting process.

Using this technique you can for example watch directory with your application via FileSystemWatcher and replace app domain on changes to application files. You can also minimize downtime by first loading new appdomain to the point before starting your nancy host, then tearing down old app domain and then start nancy host in new app domain.

Upvotes: 1

Oskar Sjöberg
Oskar Sjöberg

Reputation: 2888

If you are on Windows/IIS you can use MSDeploy to update your web app without downtime. Be aware that it will not keep any in-memory state as it will spin up the new version in a new AppDomain while the old AppDomain will be unloaded.

Upvotes: 0

Oskar Sjöberg
Oskar Sjöberg

Reputation: 2888

The only way to unload code is to unload an entire AppDomain. This means that you probably want to to create a new AppDomain for every Assembly that you load dynamically.

This example gives you a starting point on how to create a new AppDomain and how to call code loaded into another AppDomain: https://stackoverflow.com/a/2648592/540832

Upvotes: 2

Related Questions