ASP.NET Core With Kestrel and Service Fabric

DZone 's Guide to

ASP.NET Core With Kestrel and Service Fabric

Tips on using Azure's Service Fabric with ASP.NET Core to easily include a web app or service in your Service Fabric app.

· Web Dev Zone ·
Free Resource

Service Fabric SDK 2.1.150 comes with an ASP.NET Core project template so you can easily include a web app or web service in your Service Fabric application. To get started follow this official article: Build a web service front end for your application, but for more advanced scenarios such as hosting your .Net Core web applications outside Service Fabric (for those times you just don’t want to deploy), forcing Kestrel to listen to all machine assigned IP addresses, we’ll customize and extend the starter template generated code. Moreover, with .Net Core RC2 and RTM, the ubiquitous dotnet.exe becomes our preferred tool of choice, so let’s facilitate running your Service Fabric Web app for development and debugging with the same simple command: dotnet.exe run.

As always, and given I am still targeting .Net Core RC2, we’ll start with the required project.json dependencies, which should look something like below. For command line argument heavy lifting, include the “CommandLineParser”: “2.0.275-beta” package.

"dependencies": {
    "Microsoft.AspNetCore.Hosting": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Authentication": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Authentication.Cookies": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Authentication.JwtBearer": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Authentication.OpenIdConnect": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Diagnostics": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.SpaServices": "1.0.0-beta-000004",
    "Microsoft.AspNetCore.StaticFiles": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Mvc": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Mvc.Formatters.Json": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final",  
    "Microsoft.Extensions.Configuration.Abstractions": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.Json": "1.0.0-rc2-final",
    "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.9.302261508-alpha",
    "Microsoft.Extensions.Configuration.Binder": "1.0.0-rc2-final",
    "Swashbuckle": "6.0.0-beta9",
    "Swashbuckle.SwaggerUi": "6.0.0-beta9",
    "Swashbuckle.SwaggerGen": "6.0.0-beta9",
    "CommandLineParser": "2.0.275-beta",
    "Microsoft.ServiceFabric": "5.1.150",
    "Microsoft.ServiceFabric.Data": "2.1.150",
    "Microsoft.ServiceFabric.Services": "2.1.150",
    "Microsoft.AspNetCore.Http.Abstractions": "1.0.0-rc2-final"

In your Program.cs, which contains the generated starter template code, add the following:

using CommandLine;
using Microsoft.AspNetCore.Hosting;
using Microsoft.ServiceFabric.Services.Communication.Runtime;
using Microsoft.ServiceFabric.Services.Runtime;
using System;
using System.Collections.Generic;
using System.Fabric;
using System.Threading;
using System.Threading.Tasks;

Since we want to host our .Net Core web application both within Service Fabric and outside for quick turnaround during development and debugging, without the hassle of always deploying, we modify Main to support both scenarios:

public static void Main(string[] args)
      var parser = new Parser(with => {
            with.EnableDashDash = true;
            with.HelpWriter = Console.Out;

      var result = parser.ParseArguments<Options>(args);

      options => 
            if (options.Host.ToLower() == AcmeConstants.ServiceFabricHost)
                  ServiceRuntime.RegisterServiceAsync("WebType", context => new WebHostingService(context, "WebTypeEndpoint")).GetAwaiter().GetResult();
            else if(options.Host.ToLower() == AcmeConstants.SelfHost)
                  using (var host = WebHostBuilderHelper.GetWebHost(new WebHostBuilder(), options.Protocol, options.Port))
            return 0;
      errors => 
            return 1;


  • AcmeConstants.ServiceFabricHost — Value of command line argument: service-fabric-host

  • AcmeConstants.SelfHost — Value of command line argument: self-host

We then need to create an Options class to be used by the CommandLineParser:

internal sealed class Options
      [Option(Default = "self-host", HelpText = "The target host - Options [self-host] or [service-fabric-host]")]
      public string Host { get; set; }

      [Option(Default = "http", HelpText = "The target protocol - Options [http] or [https]")]
      public string Protocol { get; set; }

      [Option(Default = "localhost", HelpText = "The target IP Address or Uri - Example [localhost] or []")]
      public string IpAddressOrFQDN { get; set; }

      [Option(Default = "5000", HelpText = "The target port - Example [80] or [5000]")]
      public string Port { get; set; }

We replace the generated OpenAsync code with the following version:

Task<string> ICommunicationListener.OpenAsync(CancellationToken cancellationToken)
      var endpoint = FabricRuntime.GetActivationContext().GetEndpoint(_endpointName);
      string serverUrl = $"{endpoint.Protocol}://{FabricRuntime.GetNodeContext().IPAddressOrFQDN}:{endpoint.Port}";

      _webHost = WebHostBuilderHelper.GetWebHost(new WebHostBuilder(), endpoint.Protocol.ToString(), endpoint.Port.ToString());

      return Task.FromResult(serverUrl);

Lastly we create our common GetWebHost method:

public static class WebHostBuilderHelper
      public static IWebHost GetWebHost(IWebHostBuilder webHostBuilder, string protocol, string port)
            IWebHost webHost = webHostBuilder
                  .UseWebRoot(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot"))

            return webHost;

Note, I prefer to use the following which instructs Kestrel to listen to all IP addresses assigned to the machine on the port specified: .UseUrls($"{protocol}://+:{port}"

All that is now left to do is within your .Net Core Web Application PackageRoot, edit the ServiceManifest.xml CodePackage so that we tell Web.exe to “host” itself within Service Fabric in this scenario:

<CodePackage Name="C" Version="1.0.0">
        <Arguments>--host service-fabric-host</Arguments>
        <ConsoleRedirection FileRetentionCount="5" FileMaxSizeInKb="2048" />

Your .Net Core Web application will now run both within Service Fabric and in debug mode. To run from the command line, from within your Web application folder, issue dotnet.exe run.

.net, asp.net core, core, microservices, microsoft azure, service fabric

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}