Service Fabric Web API App KickStart - egnomerator/misc GitHub Wiki

Kick-Starting a Service Fabric Web API Application

These steps setup a skeleton Service Fabric Stateless Reliable Service Web API application

This guide just covers an optional set of kick-starting steps and hardly scratches the surface of the universe of Service Fabric.

Assumptions

  • Have already installed the Service Fabric SDK and tools
    • There are different versions of the Service Fabric SDK depending on the environment
    • Service Fabric SDK versions here
  • Using Visual Studio 2015 (although these steps will probably work with VS 2017 as well)
  • Familiarity with .NET, C#, ASP.NET MVC
    • This kick-start guide goes through steps specific to setting up a Service Fabric application

note: This is not meant to be a tutorial in the sense of explaining concepts or code, it's just a guide to quickly get something simple running. See the Service Fabric docs to research the concepts and code

Steps

  1. Create new project
    • Cloud node (exists if SF SDK is installed)
    • Choose Service Fabric Application and provide a name
      • This guide's example is named MySfApp
    • Choose Stateless Service and provide name
      • This guide's example is named MyStatelessService
  2. Solution is created with 2 projects initially
    • The service fabric application project (MySfApp)
      • This project is basically for packaging specifications and configurations
    • The stateless service project (MyStatelessService)
      • This is the project that will become the Web API service
  3. Set the MyStatelessService project to target .NET Framework v4.6.2 if it doesn't already
  4. In the ServiceEventSource.cs root class (in MyStatelessService project)
    • In the EventSource attribute Name value replace "MyCompany" with a company name if desired
  5. Add necessary NuGet Packages
    • Microsoft.ServiceFabric.AspNetCore.WebListener v3.0.467 (latest at time of writing this article)
      • has dependencies
    • Note: the remaining NuGet packages' versions are chosen due to being the latest version compatible with .NET Framework
    • Microsoft.AspNetCore.Mvc v1.1.6
      • has dependencies
    • Microsoft.AspNetCore.Mvc.Formatters.Xml v1.1.6
    • Microsoft.Extensions.Configuration.FileExtensions v1.1.2
    • Microsoft.Extensions.Configuration.Json v1.1.2
    • Microsoft.Extensions.Logging.Console v1.1.2
    • Microsoft.Extensions.Logging.Debug v1.1.2
  6. Add Startup.cs class file to MyStatelessService project root
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    
    namespace MyStatelessService
    {
        public class Startup
        {
            public Startup(IHostingEnvironment env)
            {
                var builder = new ConfigurationBuilder()
                    .SetBasePath(env.ContentRootPath)
                    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                    .AddEnvironmentVariables();
                Configuration = builder.Build();
            }
    
            public IConfigurationRoot Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                // Add framework services.
                services.AddMvc(options => { options.RespectBrowserAcceptHeader = true; })
                    .AddXmlSerializerFormatters();
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
            {
                loggerFactory.AddConsole(Configuration.GetSection("Logging"));
                loggerFactory.AddDebug();
    
                app.UseMvc();
            }
        }
    }
  7. Edit the existing class named after MyStatelessService project name (located in the project root)
    • Remove the unnecessary RunAsync method
    • Edit the CreateServiceInstanceListeners method
      • Replace return new ServiceInstanceListener[0]; (template code)
      • With this code (notice it uses the above Startup class):
        return new[]
        {
            new ServiceInstanceListener(serviceContext =>
                new WebListenerCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
                {
                    ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting WebListener on {url}");
        
                    return new WebHostBuilder()
                                .UseWebListener()
                                .ConfigureServices(
                                    services => services
                                        .AddSingleton<StatelessServiceContext>(serviceContext))
                                .UseContentRoot(Directory.GetCurrentDirectory())
                                .UseStartup<Startup>()
                                .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                                .UseUrls(url)
                                .Build();
                }))
        };
  8. Edit ServiceManifest.xml file in the PackageRoot folder of MyStatelessService project
    • Update the Endpoint element
      <Endpoint Protocol="http" Name="ServiceEndpoint" Type="Input" Port="80" />
  9. Edit ApplicationManifest.xml file in the ApplicationPackageRoot folder of MySfApp project
    • Update the Parameter element's DefaultValue attribute value to 1
      • (template code sets it to -1 indicating max available)
  10. Edit files in the ApplicationParameters folder of MySfApp project
    • Files
      • Cloud.xml
      • Local.1Node.xml (may not need to be edited)
      • Local.5Node.xml (may not need to be edited)
    • Update the Parameter element's Value attribute value to 1
      • (in Cloud.xml file, template code sets it to -1 indicating max available)
  11. Create a Controllers folder within MyStatelessService project root
  12. Within the new Controllers folder create a new class implementing the Controller class (namespace Microsoft.AspNetCore.Mvc)
    • This guide's example: HelloSFController
  13. Add the code to the controller
    using System.Collections.Generic;
    using Microsoft.AspNetCore.Mvc;
    
    namespace MyStatelessService.Controllers
    {
        [Route("api/[controller]")]
        public class HelloSFController: Controller
        {
            // GET api/hellosf
            [HttpGet]
            public IEnumerable<string> Get()
            {
                return new List<string> {"Hello", "From", "Service", "Fabric"};
            }
        }
    }
  14. Run the app in debug mode
    • It may take a little while for the app to be running and ready to test
    • Access the local cluster manager (web interface) via the system tray icon
  15. Test the GET call
    • Test with a utility that can call against Web APIs like curl, Postman, Fiddler, etc.
    curl http://localhost:80/api/hellosf
    
⚠️ **GitHub.com Fallback** ⚠️