Host ASP.NET Core Application as a Windows Service

If you have created your application in ASP.NET Core then might be there is new requirement of hosting this application as windows services. Well this hosting as windows service is also available in traditional ASP.NET using the OWIN. Now ASP.NET Core is came with the hosting app as windows service with minimal effort. This article with video wil help you to understand how we can host application in windows server.

Creating a Default Web Application

We start with new default ASP.NET Core web application.

ASP.NET Core Templates Image

I didn’t configure HTTPS as this is a sample application and it does nothing important.

By default, the Program class looks like this.


public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }
    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup();
}

Now we have working default application and it’s time to focus on the Windows service.

Running an ASP.NET Core Application as a Windows Service

Running the application as a Windows service takes some effort before we can open the browser and see it running under the service. First, we have to specify a runtime for our application, as ASP.NET Core also supports operating systems and architectures where Windows services don’t run. For this, we have to modify the project file.


<Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
        <TargetFramework>netcoreapp2.1</TargetFramework>
        <RuntimeIdentifier>win7-x64</RuntimeIdentifier>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Microsoft.AspNetCore.App" />
    </ItemGroup>
</Project>

Next, add a reference to the NuGet package Microsoft.AspNetCore.Hosting.WindowsServices and get more information from microsoft document for Microsoft.AspNetCore.Hosting.WindowsServices. This package has everything needed to run an ASP.NET Core application as a Windows service.

We also have to modify the Main() method of the Program class. In its simplest form, the Main() method looks like this.

All we have to do now is to publish our application, register it as a Windows service, and start the service.

Running the Application as a Service or on a Console

Those who have built Windows services before, know very well that the debugging of services can be a pain in one specific anatomical area as after building the service one has to deploy new version of it, attach a debugger, etc. There is simple way around – we make our Windows service run also as a console application that is easy to run on debugger from Visual Studio.

We can apply the same trick also with ASP.NET Core application that is running as Windows service.


public static void Main(string[] args)
{
    //Check for the Debugger is attached or not if attached then run the application in IIS or IISExpress
    var isService = false;

    //when the service start we need to pass the --service parameter while running the .exe
    if(Debugger.IsAttached == false && args.Contains("--service"))
    {
        isService = true;
    }                        

    if (isService)
    {
        //Get the Content Root Directory
        var pathToContentRoot = Directory.GetCurrentDirectory();

        //If the args has the console element then than make it in array.
        var webHostArgs = args.Where(arg => arg != "--console").ToArray();

        string ConfigurationFile = ""; //Configuration file.
        string PortNo = ""; //Port

        var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
        pathToContentRoot = Path.GetDirectoryName(pathToExe);
                
        //Get the json file and read the service port no if available in the json file.
        string AppJsonFilePath = Path.Combine(pathToContentRoot, ConfigurationFile);

        if (File.Exists(AppJsonFilePath))
        {
            using (StreamReader sr = new StreamReader(AppJsonFilePath))
            {
                string jsonData = sr.ReadToEnd();
                JObject jObject = JObject.Parse(jsonData);
                if (jObject["ServicePort"] != null)                            
                    portNo = jObject["ServicePort"].ToString();                        
                            
            }
        }                 

        var host = WebHost.CreateDefaultBuilder(webHostArgs)
        .UseContentRoot(pathToContentRoot)
        .UseStartup()
        .UseUrls("http://localhost:" + portNo)
        .Build();

        host.RunAsService();
    }
    else
    {
        CreateHostBuilder(args).Build().Run();
    }

}

The json file structure is as follow.


{
    "ConnectionStrings": {
        "DefaultConnection": "Your database connection string"
    },
    "ServicePort": 5001
}

The code shown may seem a little tricky. Here are my explanations:

  • To run the application on the console from Visual Studio we control if the debugger is attached. If we want to run the application as a console application outside of Visual Studio we can use the -console argument and --service argument when we run it from the windows service.
  • When the application runs as a web application under the web server, we must use the current directory as the content root. But when the application runs as a service, we need an executable path as the content root.

Now try to run the application from Visual Studio. It starts as a usual web application.

Making the Application Run as a Windows Service

To make the application run as Windows service we need some additional steps.

  1. Publish the application to some folder.
  2. Open the command line in administrative permissions.
  3. Register the application as a Windows service using this command (space after “binPath=” is mandatory)  sc create AspNetWindowsService binPath= "path to my application exe --service"
  4. Start service: sc start AspNetWindowsService.
  5. When the service starts, open the browser and navigate to http://localhost:5000 to see the web application running.

Before releasing a new version of the service, the currently running instance must be stopped. For this, we can use the command sc stop AspNetWindowsService. To remove the service, run the following command: sc delete AspNetWindowsService.

Summary

With the new Microsoft.AspNetCore.Hosting.WindowsServices NuGet package, it is easy to run ASP.NET Core applications as Windows services. We had to modify project file a little bit and make the application’s Main() method in order to understand if an application runs as a service or a console application. Using this trick, we are able to build a web application on Visual Studio and run it as a typical web application. Our burden to get a web application running as Windows service was minimal.

Posted in Windows Hosting.