Category Archives: Windows

Worker Service in .NET Core 3.1

By Shahed C on June 17, 2020

This is the twenty-third of a new series of posts on ASP .NET Core 3.1 for 2020. In this series, we’ll cover 26 topics over a span of 26 weeks from January through June 2020, titled ASP .NET Core A-Z! To differentiate from the 2019 series, the 2020 series will mostly focus on a growing single codebase (NetLearner!) instead of new unrelated code snippets week.

Previous post:

NetLearner on GitHub:

NOTE: The Worker Service sample is a meta project that generates Word documents from blog posts, to auto-generate an ebook from this blog series. You can check out the code in the following experimental subfolder, merged from a branch:

In this Article:

W is for Worker Service

When you think of ASP .NET Core, you probably think of web application backend code, including MVC and Web API. MVC Views and Razor Pages also allow you to use backend code to generate frontend UI with HTML elements. The all-new Blazor goes one step further to allow client-side .NET code to run in a web browser, using WebAssembly. And finally, we now have a template for Worker Service applications.

Released with ASP .NET Core 3.0, the new project type was introduced in ASP .NET Core early previews. Although the project template was initially listed under the Web templates, it has since been relocated one level up in the New Project wizard. This is a great way to create potentially long-running cross-platform services in .NET Core. This article covers the Windows operating system.

Cross-platform .NET Core Worker Service

New Worker Service Project

The quickest way to create a new Worker Service project in Visual Studio 2019 is to use the latest template available with .NET Core 3.1. You may also use the appropriate dotnet CLI command.

Launch Visual Studio and select the Worker service template as shown below. After selecting the location, verify the version number (e.g. .NET Core 3.1) to create the worker service project.

Worker Service template in Visual Studio 2019
Worker Service on .NET Core 3.1

To use the Command Line, simply use the following command:

> dotnet new worker -o myproject

where -o is an optional flag to provide the output folder name for the project.

You can learn more about this template at the following location:

Program and BackgroundService

The Program.cs class contains the usual Main() method and a familiar CreateHostBuilder() method. This can be seen in the snippet below:

public class Program
{
   public static void Main(string[] args)
   {
      CreateHostBuilder(args).Build().Run();
   }

   public static IHostBuilder CreateHostBuilder(string[] args) =>
      Host.CreateDefaultBuilder(args)
      .ConfigureServices(hostContext, services =>
      {
         services.AddHostedService<Worker>();
      });
 }

Things to note:

  1. The Main method calls the CreateHostBuilder() method with any passed parameters, builds it and runs it.
  2. As of ASP .NET Core 3.0, the Web Host Builder has been replaced by a Generic Host Builder. The so-called Generic Host Builder was covered in an earlier blog post in this series.
  3. CreateHostBuilder() creates the host and configures it by calling AddHostService<T>, where T is an IHostedService, e.g. a worker class that is a child of BackgroundService

The worker class, Worker.cs, is defined as shown below:

public class Worker : BackgroundService
{
   // ...
 
   protected override async Task ExecuteAsync(CancellationToken stoppingToken)
   {
      // do stuff here
   }
}

Things to note:

  1. The worker class implements the BackgroundService class, which comes from the namespace Microsoft.Extensions.Hosting
  2. The worker class can then override the ExecuteAsync() method to perform any long-running tasks.

In the sample project, a utility class (DocEngine.cs) is used to convert a web page (e.g. a blog post or article) into a Word document for offline viewing. Fun fact: when this A-Z series wraps up, the blog posts will be assembled into a free ebook, by using this DocMaker, which uses some 3rd-party NuGet packages to generate the Word document.

Logging in a Worker Service

Logging in ASP .NET Core has been covered in great detail in an earlier blog post in this series. To get a recap, take a look at the following writeup:

To use Logging in your Worker Service project, you may use the following code in your Program.cs class:

using Microsoft.Extensions.Logging;
public static IHostBuilder CreateHostBuilder(string[] args) =>
 Host.CreateDefaultBuilder(args)
 .ConfigureLogging(loggerFactory => loggerFactory.AddEventLog())
 .ConfigureServices((hostContext, services) =>
 {
    services.AddHostedService<Worker>();
 });
  1. Before using the extension method, add its NuGet package to your project:
    • Microsoft.Extensions.Logging.EventLog
  2. Add the appropriate namespace to your code:
    • using Microsoft.Extensions.Logging;
  3. Call the method ConfigureLogging() and call the appropriate logging method, e.g. AddEventLog()

The list of available loggers include:

  • AddConsole()
  • AddDebug()
  • AddEventLog()
  • AddEventSourceLogger()

The Worker class can then accept an injected ILogger<Worker> object in its constructor:

private readonly ILogger<Worker> _logger;

public Worker(ILogger<Worker> logger)
{
   _logger = logger;
}

Running the Worker Service

NOTE: Run Powershell in Administrator Mode before running the commands below.

Before you continue, add a call to UseWindowsService() in your Program class, or verify that it’s already there. To call UseWindowsService(), the following package must be installed in your project: Microsoft.Extensions.Hosting.WindowsServices

The official announcement and initial document referred to UseServiceBaseLifetime() in an earlier preview. This method was renamed to UseWindowsService() before release.

   public static IHostBuilder CreateHostBuilder(string[] args) =>
      Host.CreateDefaultBuilder(args)
      .UseWindowsService()
      .ConfigureServices(hostContext, services =>
      {
         services.AddHostedService<Worker>();
      });

According to the code documentation, UseWindowsService() does the following:

  1. Sets the host lifetime to WindowsServiceLifetime
  2. Sets the Content Root
  3. Enables logging to the event log with the application name as the default source name

You can run the Worker Service in various ways:

  1. Build and Debug/Run from within Visual Studio.
  2. Publish to an exe file and run it
  3. Run the sc utility (from Windows\System32) to create a new service

To publish the Worker Service as an exe file with dependencies, run the following dotnet command:

dotnet publish -o C:\path\to\project\pubfolder

The -o parameter can be used to specify the path to a folder where you wish to generate the published files. It could be the path to your project folder, followed by a new subfolder name to hold your published files, e.g. pubfolder. Make a note of your EXE name, e.g. MyProjectName.exe but omit the pubfolder from your source control system.

To create a new service, run sc.exe from your System32 folder and pass in the name of the EXE file generated from the publish command.

> C:\Windows\System32\sc create MyServiceName binPath=C:\path\to\project\pubfolder\MyProjectName.exe

When running the sample manually, you should see some logging messages, as shown below:

info: DocMaker.Worker[0]
 Making doc 1 at: 06/09/2020 00:09:52 -04:00
Making your document...
info:  DocMaker.Worker[0]
 Making doc 2 at: 06/09/2020 00:10:05 -04:00
Making your document...

After the service is installed, it should show up in the operating system’s list of Windows Services:

Windows Services, showing custom Worker Service

NOTE: When porting to other operating systems, the call to UseWindowsService() is safe to leave as is. It doesn’t do anything on a non-Windows system.

References

Worker Service in ASP .NET Core

By Shahed C on June 10, 2019

This is the twenty-third of a series of posts on ASP .NET Core in 2019. In this series, we’ll cover 26 topics over a span of 26 weeks from January through June 2019, titled A-Z of ASP .NET Core!

ASPNETCoreLogo-300x267 A – Z of ASP .NET Core!

In this Article:

W is for Worker Service

When you think of ASP .NET Core, you probably think of web application backend code, including MVC and Web API. MVC Views and Razor Pages also allow you to use backend code to generate frontend UI with HTML elements. The all-new Blazor goes one step further to allow client-side .NET code to run in a web browser, using WebAssembly. And finally, we now have a template for Worker Service applications.

Briefly mentioned in a previous post in this series, the new project type was introduced in ASP .NET Core early previews. Although the project template is currently listed under the Web templates, it is expected to be relocated one level up in the New Project Wizard. This is a great way to create potentially long-running cross-platform services in .NET Core. This article covers the Windows operating system.

WorkerService-Linux-Windows

This article will refer to the following sample code on GitHub:

Web Worker Service Sample: https://github.com/shahedc/WorkerServiceSample

New Worker Service Project

The quickest way to create a new Worker Service project in Visual Studio 2019 is to use the latest template available for ASP .NET Core 3.0. You may also use the appropriate dotnet CLI command.

Launch Visual Studio and select the Worker service template as shown below:

WorkerService-NewProject

To use the Command Line, simply use the following command:

> dotnet new worker -o myproject

where -o is an optional flag to provide the output folder name for the project.

You can learn more about the new template at the following location:

Program and BackgroundService

The Program.cs class contains the usual Main() method and a familiar CreateHostBuilder() method. This can be seen in the snippet below:

public class Program
{
   public static void Main(string[] args)
   {
      CreateHostBuilder(args).Build().Run();
   }

   public static IHostBuilder CreateHostBuilder(string[] args) =>
      Host.CreateDefaultBuilder(args)
      .UseWindowsService()
      .ConfigureServices(services =>
      {
         services.AddHostedService<Worker>();
      });
 }

Things to note:

  1. The Main method calls the CreateHostBuilder() method with any passed parameters, builds it and runs it.
  2. As of ASP .NET Core 3.0, the Web Host Builder is being replaced by a Generic Host Builder. The so-called Generic Host Builder was covered in an earlier blog post in this series.
  3. CreateHostBuilder() creates the host and configures it by calling AddHostService<T>, where T is an IHostedService, e.g. a worker class that is a child of BackgroundService

The worker class, Worker.cs, is defined as shown below:

public class Worker : BackgroundService
{
   // ...
 
   protected override async Task ExecuteAsync(CancellationToken stoppingToken)
   {
      // do stuff here
   }
}

Things to note:

  1. The worker class implements the BackgroundService class, which comes from the namespace Microsoft.Extensions.Hosting
  2. The worker class can then override the ExecuteAsync() method to perform any long-running tasks.

In the sample project, a utility class (DocMaker.cs) is used to convert a web page (e.g. a blog post or article) into a Word document for offline viewing. Fun fact: when this A-Z series wraps up, the blog posts will be assembled into a free ebook, by using this EbookMaker, which uses some 3rd-party NuGet packages to generate the Word document.

Logging in a Worker Service

Logging in ASP .NET Core has been covered in great detail in an earlier blog post in this series. To get a recap, take a look at the following writeup:

To use Logging in your Worker Service project, you may use the following code in your Program.cs class:

using Microsoft.Extensions.Logging;
public static IHostBuilder CreateHostBuilder(string[] args) =>
 Host.CreateDefaultBuilder(args)
 .UseWindowsService()
 .ConfigureLogging(loggerFactory => loggerFactory.AddEventLog())
 .ConfigureServices(services =>
 {
    services.AddHostedService<Worker>();
 });
  1. Before using the extension method, add its NuGet package to your project:
    • Microsoft.Extensions.Logging.EventLog
  2. Add the appropriate namespace to your code:
    • using Microsoft.Extensions.Logging;
  3. Call the method ConfigureLogging() and call the appropriate logging method, e.g. AddEventLog()

The list of available loggers include:

  • AddConsole()
  • AddDebug()
  • AddEventLog()
  • AddEventSourceLogger()

The Worker class can then accept an injected ILogger<Worker> object in its constructor:

private readonly ILogger<Worker> _logger;

public Worker(ILogger<Worker> logger)
{
   _logger = logger;
}

Running the Worker Service

NOTE: Run Powershell in Administrator Mode before running the commands below.

Before you continue, add a call to UseWindowsService() in your Program class, or verify that it’s already there. The official announcement and initial document referred to UseServiceBaseLifetime() in an earlier preview. This method has been renamed to UseWindowsService() in the most recent version.

   public static IHostBuilder CreateHostBuilder(string[] args) =>
      Host.CreateDefaultBuilder(args)
      .UseWindowsService()
      .ConfigureServices(services =>
      {
         services.AddHostedService<Worker>();
      });

According to the code documentation, UseWindowsService() does the following:

  1. Sets the host lifetime to WindowsServiceLifetime
  2. Sets the Content Root
  3. Enables logging to the event log with the application name as the default source name

You can run the Worker Service in various ways:

  1. Build and Debug/Run from within Visual Studio.
  2. Publish to an exe file and run it
  3. Run the sc utility (from Windows\System32) to create a new service

To publish the Worker Service as an exe file with dependencies, run the following dotnet command:

dotnet publish -o C:\path\to\project\pubfolder

The -o parameter can be used to specify the path to a folder where you wish to generate the published files. It could be the path to your project folder, followed by a new subfolder name to hold your published files, e.g. pubfolder. Make a note of your EXE name, e.g. MyProjectName.exe but omit the pubfolder from your source control system.

To create a new service, run sc.exe from your System32 folder and pass in the name of the EXE file generated from the publish command.

> C:\Windows\System32\sc create MyServiceName binPath=C:\path\to\project\pubfolder\MyProjectName.exe

When running the service manually, you should see some logging messages, as shown below:

info: WorkerServiceSample.Worker[0]
 Making doc 1 at: 06/09/2019 00:09:52 -04:00
Making your document...
info: WorkerServiceSample.Worker[0]
 Making doc 2 at: 06/09/2019 00:10:05 -04:00
Making your document...
info: Microsoft.Hosting.Lifetime[0]
 Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
 Hosting environment: Development

After the service is installed, it should show up in the operating system’s list of Windows Services:

WorkerService-WindowsServices

NOTE: When porting to other operating systems, the call to UseWindowsService() is safe to leave as is. It doesn’t do anything on a non-Windows system.

References

IIS Hosting for ASP .NET Core Web Apps

By Shahed C on March 4, 2019

This is the ninth of a series of posts on ASP .NET Core in 2019. In this series, we’ll cover 26 topics over a span of 26 weeks from January through June 2019, titled A-Z of ASP .NET Core!

ASPNETCoreLogo-300x267 A – Z of ASP .NET Core!

In this Article:

I is for IIS Hosting

If you’ve been reading my weekly blog posts in this series (or you’ve worked with ASP .NET Core), you probably know that ASP .NET Core web apps can run on multiple platforms. Since Microsoft’s IIS (Internet Information Services) web server only runs on Windows, you may be wondering why we would need to know about IIS-specific hosting at all.

Well, we don’t need IIS to run ASP .NET Core, but there are some useful IIS features you can take advantage of. In fact, ASP .NET Core v2.2 introduced in-process hosting in IIS with the ASP .NET Core module. You can run your app either in-process or out of process.

From the 2.2 release notes of what’s new:

“In earlier versions of ASP.NET Core, IIS serves as a reverse proxy. In 2.2, the ASP.NET Core Module can boot the CoreCLR and host an app inside the IIS worker process (w3wp.exe). In-process hosting provides performance and diagnostic gains when running with IIS.” 

You can browse an IIS-configured sample app on GitHub at the following location:

Web IIS-configured sample: https://github.com/shahedc/IISHostedWebApp

NOTE: The actual web.config file has been intentionally left out from the above repo, and replaced with a reference file, web.config.txt. When you follow the configuration steps outlined below, the actual web.config file will be generated with the proper settings.

Blog-Diagram-IIS-in-out-proxy

Developing for IIS

In order to develop for IIS on your local development machine while working with Visual Studio, you should complete the following steps:

  1. Install/Enable IIS locally: add IIS via Windows Features setup
  2. Configure IIS: add website with desired port(s)
  3. Enable IIS support in VS: include dev-time IIS support during setup
  4. Configure your web app: enable HTTPS, add launch profile for IIS

NOTE: If you need help with any of the above steps, you may follow the detailed guide in the official docs:

After Step 1 (IIS installation), the list of Windows Features should show that IIS and many of its components have been installed.

Windows-Features-IIS

During and after Step 2 (IIS configuration), my newly added website looks like the screenshots shown below:

Add New Website

Add New Website

Explore Added Website

Explore Added Website

For Step 3 (IIS support in VS) mentioned above, make sure you select the “Development time IIS support” option under the “ASP .NET and web development” workload. These options are shown in the screenshot below:

VS2017-IIS-Setup

After Step 4 (web app config), I can run the web application locally on IIS. Check out the next section to learn more about your web application configuration. In addition to the .csproj settings, you’ll also need a web.config file in addition to your appsettings.json file.

Optionally, you could set up a VM on Azure with IIS enabled and deploy to that web server. If you need some help with the setup, you can select a pre-configured Windows VM with IIS pre-installed from the Azure Portal.

If you need help with creating an Azure VM with IIS, check out the following resources:

IIS Configuration in Visual Studio

After completing Step 4 using the instructions outlined above, let’s observe the following:

  • Profile: Debug tab in project properties
  • Project: .csproj settings
  • Settings: launchSettings.json
  • Config: web.config file

Profile: With your web project open in Visual Studio, right-click the project in Solution Explorer, and then click Properties. Click the Debug tab to see the newly-added IIS-specific profile. Note that the Hosting Model offers 3 options: Default, In-Process and Out-of-process.

VS2017-Profile-IIS

Project: Again in the Solution Explorer, right-click the project, then click Edit <projname>.csproj to view the .csproj file as a text file. Here, the <AspNetCoreHostingModel> setting is shown set to InProcess, and can be changed to OutOfProcess if desired.

VS2017-IIS-csproj

Settings: Under the Properties node in the Solution Explorer, open the launchSettings.json file. Here, you can see all the settings for your newly-created IIS-specific Profile. You can manually add/edit settings directly in this file without having to use the Visual Studio UI.

VS2017-IIS-launch

Config: You may recognize the XML-based web.config file from previous versions of ASP .NET, but the project’s settings and dependencies are now spread across multiple files, such as the .csproj file and appsettings.json config file. For ASP .NET Core projects, the web.config file is only used specifically for an IIS-hosted environment. In this file, you may configure the ASP .NET Core Module that will be used for your IIS-hosted web application.

VS2017-IIS-webconfig

Once your web app is configured, you can run it from Visual Studio using the profile you created previously. In order to run it using a specific profile, click the tiny dropdown next to the green Run/Debug button to select the desired profile. Then click the button itself. This should launch the application in your web browser, pointing to localhost running on IIS, e.g. https://localhost/<appname>

IIS Profile

IIS Profile

Running in a browser

Running in a browser 

ASP .NET Core Module

Now that your IIS server environment has been set up (either locally or in the cloud), let’s learn about the ASP .NET Core Module. This is a native IIS module that plugs into the actual IIS pipeline (not to be confused with your web app’s request pipeline). It allows you to host your web app in one of two ways:

  • In-process: the web app is hosted inside the IIS worker process, i.e. w3wp.exe (previously known as the World Wide Web Publishing Service)
  • Out of process: IIS forwards web server requests to the web app, which uses Kestrel (the cross-platform web server included with ASP .NET Core)

As you’ve seen in an earlier section, this setting is configured in the web.config file:

<PropertyGroup>
   <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>

The lists below shows shows some notable differences between hosting in-process vs out of process.

Blog-Diagram-IIS-in-out

How you configure your app is up to you. For more details on the module and its configuration settings, browse through the information available at:

BONUS: Publishing to a VM with IIS

You can publish your ASP .NET Core web app to a Virtual Machine (either on your network or in Azure) or just any Windows Server you have access to. There are several different options:

Here are some prerequisites to be aware of:

  • IIS must be pre-installed on the server with relevant ports enabled
  • WebDeploy must be installed (which you would normally have on your local dev machine)
  • The VM must have a DNS name configured (Azure VMs can have fully qualified domain names, e.g. <machinename>.eastus.cloudapp.azure.com)

References

 

 

HoloLens + Microsoft Cognitive Services

By Shahed C on February 21, 2018

Here is the presentation material for HoloLens + Microsoft Cognitive Services, presented at San Francisco Bay Area Azure on Feb 21, 2018.

hololens-darkened

cog-logo

PPTX: https://wakeupandcode.com/public_downloads/HoloLens-CognitiveServices.pptx

Slideshare: https://www.slideshare.net/shahedC3000/cloudbacked-mixed-reality-with-hololens-azure-cognitive-services

 

Xbox One Game Dev @ .NET Conf UY

By Shahed C on November 6, 2017

I presented Azure Functions at .NET Conf UY on Fri October 27, 2017. Here is the presentation material with the slides, links and my contact information.

Xbox One

Download PPTX or view slideshow below

SlideShare: https://www.slideshare.net/shahedC3000/game-on-with-windows-xbox-one-net-conf-uy

Create and publish your own games for Windows and Xbox One, using free development tools from Microsoft and our game development partners. Use Visual Studio, C# and .NET along with Unity to build 2D or 3D experiences for gamers, with support for keyboard, mouse, touch and controllers for all major platforms to maximize your reach with less effort. Also learn about Construct 3 for simpler 2D games or prototypes, with support for modern app stores, desktop and Xbox One.