mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 20:30:50 +08:00 
			
		
		
		
	Make Ocelot work with service fabric DNS and naming service for guest exe and stateless (#242)
* test for issue * added service fabric sample * working!! * changed sample naming to Ocelot * removed files we dont need * removed files we dont need * updated sample gitignore * updated sample gitignore * getting ocelot to work with service fabric using the reverse proxy * #238 - added support for service fabric discovery provider, proxies requests through naming service, wont work on partioned service fabric services yet * #238 - Manually tested service fabric using sample..all seems OK. Made some changes after testing, added docs * #238 - added docs for servic fabric
This commit is contained in:
		@@ -0,0 +1,31 @@
 | 
			
		||||
// ------------------------------------------------------------
 | 
			
		||||
//  Copyright (c) Microsoft Corporation.  All rights reserved.
 | 
			
		||||
//  Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
 | 
			
		||||
// ------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
namespace OcelotApplicationApiGateway
 | 
			
		||||
{
 | 
			
		||||
    using System.Fabric;
 | 
			
		||||
    using Microsoft.ServiceFabric.Services.Communication.Runtime;
 | 
			
		||||
    using Microsoft.ServiceFabric.Services.Runtime;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
    /// Service that handles front-end web requests and acts as a proxy to the back-end data for the UI web page.
 | 
			
		||||
    /// It is a stateless service that hosts a Web API application on OWIN.
 | 
			
		||||
    internal sealed class OcelotServiceWebService : StatelessService
 | 
			
		||||
    {
 | 
			
		||||
        public OcelotServiceWebService(StatelessServiceContext context)
 | 
			
		||||
            : base(context)
 | 
			
		||||
        { }
 | 
			
		||||
 | 
			
		||||
        protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
 | 
			
		||||
        {
 | 
			
		||||
            return new[]
 | 
			
		||||
            {
 | 
			
		||||
                new ServiceInstanceListener(
 | 
			
		||||
                    initparams => new WebCommunicationListener(string.Empty, initparams),
 | 
			
		||||
                    "OcelotServiceWebListener")
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,22 @@
 | 
			
		||||
<Project Sdk="Microsoft.NET.Sdk.Web">
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <Description>Stateless Web Service for Stateful OcelotApplicationApiGateway App</Description>
 | 
			
		||||
    <Authors> </Authors>
 | 
			
		||||
    <TargetFramework>netcoreapp2.0</TargetFramework>
 | 
			
		||||
    <AssemblyName>OcelotApplicationApiGateway</AssemblyName>
 | 
			
		||||
    <OutputType>Exe</OutputType>
 | 
			
		||||
    <PackageId>OcelotApplicationApiGateway</PackageId>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
    <ItemGroup>
 | 
			
		||||
    <None Update="configuration.json;appsettings.json;">
 | 
			
		||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
			
		||||
    </None>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="Microsoft.ServiceFabric" Version="6.1.456" />
 | 
			
		||||
    <PackageReference Include="Microsoft.ServiceFabric.Services" Version="3.0.456" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ProjectReference Include="..\..\..\..\src\Ocelot\Ocelot.csproj" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
</Project>
 | 
			
		||||
@@ -0,0 +1,51 @@
 | 
			
		||||
// ------------------------------------------------------------
 | 
			
		||||
//  Copyright (c) Microsoft Corporation.  All rights reserved.
 | 
			
		||||
//  Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
 | 
			
		||||
// ------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
namespace OcelotApplicationApiGateway
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Fabric;
 | 
			
		||||
    using System.Threading;
 | 
			
		||||
    using Microsoft.ServiceFabric.Services.Runtime;
 | 
			
		||||
    using System.Diagnostics.Tracing;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// The service host is the executable that hosts the Service instances.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class Program
 | 
			
		||||
    {
 | 
			
		||||
        public static void Main(string[] args)
 | 
			
		||||
        {
 | 
			
		||||
            // Create Service Fabric runtime and register the service type.
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
                //Creating a new event listener to redirect the traces to a file
 | 
			
		||||
                ServiceEventListener listener = new ServiceEventListener("OcelotApplicationApiGateway");
 | 
			
		||||
                listener.EnableEvents(ServiceEventSource.Current, EventLevel.LogAlways, EventKeywords.All);
 | 
			
		||||
 | 
			
		||||
                // The ServiceManifest.XML file defines one or more service type names.
 | 
			
		||||
                // Registering a service maps a service type name to a .NET type.
 | 
			
		||||
                // When Service Fabric creates an instance of this service type,
 | 
			
		||||
                // an instance of the class is created in this host process.
 | 
			
		||||
                ServiceRuntime
 | 
			
		||||
                    .RegisterServiceAsync("OcelotApplicationApiGatewayType", context => new OcelotServiceWebService (context))
 | 
			
		||||
                        .GetAwaiter()
 | 
			
		||||
                        .GetResult();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                // Prevents this host process from terminating so services keep running.
 | 
			
		||||
                Thread.Sleep(Timeout.Infinite);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                ServiceEventSource.Current.ServiceHostInitializationFailed(ex);
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,27 @@
 | 
			
		||||
{
 | 
			
		||||
  "iisSettings": {
 | 
			
		||||
    "windowsAuthentication": false,
 | 
			
		||||
    "anonymousAuthentication": true,
 | 
			
		||||
    "iisExpress": {
 | 
			
		||||
      "applicationUrl": "http://localhost:36034/",
 | 
			
		||||
      "sslPort": 0
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "profiles": {
 | 
			
		||||
    "IIS Express": {
 | 
			
		||||
      "commandName": "IISExpress",
 | 
			
		||||
      "launchBrowser": true,
 | 
			
		||||
      "environmentVariables": {
 | 
			
		||||
        "ASPNETCORE_ENVIRONMENT": "Development"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "OcelotApplicationApiGateway": {
 | 
			
		||||
      "commandName": "Project",
 | 
			
		||||
      "launchBrowser": true,
 | 
			
		||||
      "environmentVariables": {
 | 
			
		||||
        "ASPNETCORE_ENVIRONMENT": "Development"
 | 
			
		||||
      },
 | 
			
		||||
      "applicationUrl": "http://localhost:36035/"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,94 @@
 | 
			
		||||
// ------------------------------------------------------------
 | 
			
		||||
//  Copyright (c) Microsoft Corporation.  All rights reserved.
 | 
			
		||||
//  Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
 | 
			
		||||
// ------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
namespace OcelotApplicationApiGateway
 | 
			
		||||
{
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.IO;
 | 
			
		||||
    using System.Linq;
 | 
			
		||||
    using System.Diagnostics.Tracing;
 | 
			
		||||
    using System.Fabric;
 | 
			
		||||
    using System.Fabric.Common;
 | 
			
		||||
    using System.Fabric.Common.Tracing;
 | 
			
		||||
    using Microsoft.ServiceFabric.Services.Runtime;
 | 
			
		||||
    using System.Globalization;
 | 
			
		||||
    using System.Text;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// ServiceEventListener is a class which listens to the eventsources registered and redirects the traces to a file
 | 
			
		||||
    /// Note that this class serves as a template to EventListener class and redirects the logs to /tmp/{appnameyyyyMMddHHmmssffff}.
 | 
			
		||||
    /// You can extend the functionality by writing your code to implement rolling logs for the logs written through this class.
 | 
			
		||||
    /// You can also write your custom listener class and handle the registered evestsources accordingly. 
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    internal class ServiceEventListener : EventListener
 | 
			
		||||
    {
 | 
			
		||||
        private string fileName;
 | 
			
		||||
        private string filepath = Path.GetTempPath();
 | 
			
		||||
 | 
			
		||||
        public ServiceEventListener(string appName)
 | 
			
		||||
        {
 | 
			
		||||
            this.fileName = appName + DateTime.Now.ToString("yyyyMMddHHmmssffff");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// We override this method to get a callback on every event we subscribed to with EnableEvents
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="eventData">The event arguments that describe the event.</param>
 | 
			
		||||
        protected override void OnEventWritten(EventWrittenEventArgs eventData)
 | 
			
		||||
        {
 | 
			
		||||
            using (StreamWriter writer = new StreamWriter( new FileStream(filepath + fileName, FileMode.Append)))
 | 
			
		||||
            {
 | 
			
		||||
                // report all event information
 | 
			
		||||
                writer.Write(" {0} ",  Write(eventData.Task.ToString(),
 | 
			
		||||
                eventData.EventName,
 | 
			
		||||
                eventData.EventId.ToString(),
 | 
			
		||||
                eventData.Level));
 | 
			
		||||
 | 
			
		||||
                if (eventData.Message != null)
 | 
			
		||||
                {
 | 
			
		||||
                    writer.WriteLine(string.Format(CultureInfo.InvariantCulture, eventData.Message, eventData.Payload.ToArray()));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static String Write(string taskName, string eventName, string id, EventLevel level)
 | 
			
		||||
        {
 | 
			
		||||
            StringBuilder output = new StringBuilder();
 | 
			
		||||
 | 
			
		||||
            DateTime now = DateTime.UtcNow;
 | 
			
		||||
            output.Append(now.ToString("yyyy/MM/dd-HH:mm:ss.fff", CultureInfo.InvariantCulture));
 | 
			
		||||
            output.Append(',');
 | 
			
		||||
            output.Append(ConvertLevelToString(level));
 | 
			
		||||
            output.Append(',');
 | 
			
		||||
            output.Append(taskName);
 | 
			
		||||
 | 
			
		||||
            if (!string.IsNullOrEmpty(eventName))
 | 
			
		||||
            {
 | 
			
		||||
                output.Append('.');
 | 
			
		||||
                output.Append(eventName);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!string.IsNullOrEmpty(id))
 | 
			
		||||
            {
 | 
			
		||||
                output.Append('@');
 | 
			
		||||
                output.Append(id);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            output.Append(',');
 | 
			
		||||
            return output.ToString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static string ConvertLevelToString(EventLevel level)
 | 
			
		||||
        {
 | 
			
		||||
            switch (level)
 | 
			
		||||
            {
 | 
			
		||||
                case EventLevel.Informational:
 | 
			
		||||
                    return "Info";
 | 
			
		||||
                default:
 | 
			
		||||
                    return level.ToString();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,86 @@
 | 
			
		||||
// ------------------------------------------------------------
 | 
			
		||||
//  Copyright (c) Microsoft Corporation.  All rights reserved.
 | 
			
		||||
//  Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
 | 
			
		||||
// ------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
namespace OcelotApplicationApiGateway
 | 
			
		||||
{
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Diagnostics.Tracing;
 | 
			
		||||
    using System.Fabric;
 | 
			
		||||
    using Microsoft.ServiceFabric.Services.Runtime;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Implements methods for logging service related events.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class ServiceEventSource : EventSource
 | 
			
		||||
    {
 | 
			
		||||
        public static ServiceEventSource Current = new ServiceEventSource();
 | 
			
		||||
 | 
			
		||||
        // Define an instance method for each event you want to record and apply an [Event] attribute to it.
 | 
			
		||||
        // The method name is the name of the event.
 | 
			
		||||
        // Pass any parameters you want to record with the event (only primitive integer types, DateTime, Guid & string are allowed).
 | 
			
		||||
        // Each event method implementation should check whether the event source is enabled, and if it is, call WriteEvent() method to raise the event.
 | 
			
		||||
        // The number and types of arguments passed to every event method must exactly match what is passed to WriteEvent().
 | 
			
		||||
        // Put [NonEvent] attribute on all methods that do not define an event.
 | 
			
		||||
        // For more information see https://msdn.microsoft.com/en-us/library/system.diagnostics.tracing.eventsource.aspx
 | 
			
		||||
 | 
			
		||||
        [NonEvent]
 | 
			
		||||
        public void Message(string message, params object[] args)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.IsEnabled())
 | 
			
		||||
            {
 | 
			
		||||
                var finalMessage = string.Format(message, args);
 | 
			
		||||
                this.Message(finalMessage);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private const int MessageEventId = 1;
 | 
			
		||||
 | 
			
		||||
        [Event(MessageEventId, Level = EventLevel.Informational, Message = "{0}")]
 | 
			
		||||
        public void Message(string message)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.IsEnabled())
 | 
			
		||||
            {
 | 
			
		||||
                this.WriteEvent(MessageEventId, message);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private const int ServiceTypeRegisteredEventId = 3;
 | 
			
		||||
 | 
			
		||||
        [Event(ServiceTypeRegisteredEventId, Level = EventLevel.Informational, Message = "Service host process {0} registered service type {1}")]
 | 
			
		||||
        public void ServiceTypeRegistered(int hostProcessId, string serviceType)
 | 
			
		||||
        {
 | 
			
		||||
            this.WriteEvent(ServiceTypeRegisteredEventId, hostProcessId, serviceType);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [NonEvent]
 | 
			
		||||
        public void ServiceHostInitializationFailed(Exception e)
 | 
			
		||||
        {
 | 
			
		||||
            this.ServiceHostInitializationFailed(e.ToString());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private const int ServiceHostInitializationFailedEventId = 4;
 | 
			
		||||
 | 
			
		||||
        [Event(ServiceHostInitializationFailedEventId, Level = EventLevel.Error, Message = "Service host initialization failed: {0}")]
 | 
			
		||||
        private void ServiceHostInitializationFailed(string exception)
 | 
			
		||||
        {
 | 
			
		||||
            this.WriteEvent(ServiceHostInitializationFailedEventId, exception);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [NonEvent]
 | 
			
		||||
        public void ServiceWebHostBuilderFailed(Exception e)
 | 
			
		||||
        {
 | 
			
		||||
            this.ServiceWebHostBuilderFailed(e.ToString());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private const int ServiceWebHostBuilderFailedEventId = 5;
 | 
			
		||||
 | 
			
		||||
        [Event(ServiceWebHostBuilderFailedEventId, Level = EventLevel.Error, Message = "Service Owin Web Host Builder Failed: {0}")]
 | 
			
		||||
        private void ServiceWebHostBuilderFailed(string exception)
 | 
			
		||||
        {
 | 
			
		||||
            this.WriteEvent(ServiceWebHostBuilderFailedEventId, exception);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,125 @@
 | 
			
		||||
// ------------------------------------------------------------
 | 
			
		||||
//  Copyright (c) Microsoft Corporation.  All rights reserved.
 | 
			
		||||
//  Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
 | 
			
		||||
// ------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
namespace OcelotApplicationApiGateway
 | 
			
		||||
{
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Fabric;
 | 
			
		||||
    using System.Fabric.Description;
 | 
			
		||||
    using System.Globalization;
 | 
			
		||||
    using System.Threading;
 | 
			
		||||
    using System.Threading.Tasks;
 | 
			
		||||
    using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
    using Microsoft.ServiceFabric.Services.Communication.Runtime;
 | 
			
		||||
    using Microsoft.Extensions.Logging;
 | 
			
		||||
    using Microsoft.Extensions.Configuration;
 | 
			
		||||
    using Microsoft.AspNetCore.Builder;
 | 
			
		||||
    using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
    using Ocelot.DependencyInjection;
 | 
			
		||||
    using Ocelot.Middleware;
 | 
			
		||||
 | 
			
		||||
    public class WebCommunicationListener : ICommunicationListener
 | 
			
		||||
    {
 | 
			
		||||
        private readonly string appRoot;
 | 
			
		||||
        private readonly ServiceContext serviceInitializationParameters;
 | 
			
		||||
        private string listeningAddress;
 | 
			
		||||
        private string publishAddress;
 | 
			
		||||
 | 
			
		||||
        // OWIN server handle.
 | 
			
		||||
        private IWebHost webHost;
 | 
			
		||||
 | 
			
		||||
        public WebCommunicationListener(string appRoot, ServiceContext serviceInitializationParameters)
 | 
			
		||||
        {
 | 
			
		||||
            this.appRoot = appRoot;
 | 
			
		||||
            this.serviceInitializationParameters = serviceInitializationParameters;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Task<string> OpenAsync(CancellationToken cancellationToken)
 | 
			
		||||
        {
 | 
			
		||||
            ServiceEventSource.Current.Message("Initialize");
 | 
			
		||||
 | 
			
		||||
            EndpointResourceDescription serviceEndpoint = this.serviceInitializationParameters.CodePackageActivationContext.GetEndpoint("WebEndpoint");
 | 
			
		||||
            int port = serviceEndpoint.Port;
 | 
			
		||||
 | 
			
		||||
            this.listeningAddress = string.Format(
 | 
			
		||||
                CultureInfo.InvariantCulture,
 | 
			
		||||
                "http://+:{0}/{1}",
 | 
			
		||||
                port,
 | 
			
		||||
                string.IsNullOrWhiteSpace(this.appRoot)
 | 
			
		||||
                    ? string.Empty
 | 
			
		||||
                    : this.appRoot.TrimEnd('/') + '/');
 | 
			
		||||
 | 
			
		||||
            this.publishAddress = this.listeningAddress.Replace("+", FabricRuntime.GetNodeContext().IPAddressOrFQDN);
 | 
			
		||||
 | 
			
		||||
            ServiceEventSource.Current.Message("Starting web server on {0}", this.listeningAddress);
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                this.webHost = new WebHostBuilder()
 | 
			
		||||
               .UseKestrel()
 | 
			
		||||
               //.UseStartup<Startup>()
 | 
			
		||||
               .UseUrls(this.listeningAddress)
 | 
			
		||||
                .ConfigureAppConfiguration((hostingContext, config) =>
 | 
			
		||||
                {
 | 
			
		||||
                    config
 | 
			
		||||
                        .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
 | 
			
		||||
                        .AddJsonFile("appsettings.json", true, true)
 | 
			
		||||
                        .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
 | 
			
		||||
                        .AddJsonFile("configuration.json")
 | 
			
		||||
                        .AddEnvironmentVariables();
 | 
			
		||||
                })
 | 
			
		||||
               .ConfigureLogging((hostingContext, logging) =>
 | 
			
		||||
                {
 | 
			
		||||
                    logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
 | 
			
		||||
                    logging.AddConsole();
 | 
			
		||||
                })
 | 
			
		||||
                .ConfigureServices(s => {
 | 
			
		||||
                    s.AddOcelot();
 | 
			
		||||
                })
 | 
			
		||||
                .Configure(a => {
 | 
			
		||||
                    a.UseOcelot().Wait();
 | 
			
		||||
                })
 | 
			
		||||
               .Build();
 | 
			
		||||
 | 
			
		||||
                this.webHost.Start();
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                ServiceEventSource.Current.ServiceWebHostBuilderFailed(ex);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return Task.FromResult(this.publishAddress);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Task CloseAsync(CancellationToken cancellationToken)
 | 
			
		||||
        {
 | 
			
		||||
            this.StopAll();
 | 
			
		||||
            return Task.FromResult(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Abort()
 | 
			
		||||
        {
 | 
			
		||||
            this.StopAll();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Stops, cancels, and disposes everything.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void StopAll()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (this.webHost != null)
 | 
			
		||||
                {
 | 
			
		||||
                    ServiceEventSource.Current.Message("Stopping web server.");
 | 
			
		||||
                    this.webHost.Dispose();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (ObjectDisposedException)
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,10 @@
 | 
			
		||||
{
 | 
			
		||||
  "Logging": {
 | 
			
		||||
    "IncludeScopes": false,
 | 
			
		||||
    "LogLevel": {
 | 
			
		||||
      "Default": "Trace",
 | 
			
		||||
      "System": "Information",
 | 
			
		||||
      "Microsoft": "Information"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,22 @@
 | 
			
		||||
{
 | 
			
		||||
  "ReRoutes": [
 | 
			
		||||
    {
 | 
			
		||||
      "DownstreamPathTemplate": "/api/values",
 | 
			
		||||
      "UpstreamPathTemplate": "/EquipmentInterfaces",
 | 
			
		||||
      "UpstreamHttpMethod": [
 | 
			
		||||
        "Get"
 | 
			
		||||
      ],
 | 
			
		||||
      "DownstreamScheme": "http",
 | 
			
		||||
      "ServiceName": "OcelotServiceApplication/OcelotApplicationService",
 | 
			
		||||
      "UseServiceDiscovery" :  true
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "GlobalConfiguration": {
 | 
			
		||||
    "RequestIdKey": "OcRequestId",
 | 
			
		||||
    "ServiceDiscoveryProvider": {
 | 
			
		||||
      "Host": "localhost",
 | 
			
		||||
      "Port": 19081,
 | 
			
		||||
      "Type": "ServiceFabric"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,59 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Fabric;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Microsoft.ServiceFabric.Services.Communication.AspNetCore;
 | 
			
		||||
using Microsoft.ServiceFabric.Services.Communication.Runtime;
 | 
			
		||||
using Microsoft.ServiceFabric.Services.Runtime;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
 | 
			
		||||
namespace OcelotApplicationService
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// The FabricRuntime creates an instance of this class for each service type instance. 
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    internal sealed class ApiGateway : StatelessService
 | 
			
		||||
    {
 | 
			
		||||
        public ApiGateway(StatelessServiceContext context)
 | 
			
		||||
            : base(context)
 | 
			
		||||
        { }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Optional override to create listeners (like tcp, http) for this service instance.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The collection of listeners.</returns>
 | 
			
		||||
        protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
 | 
			
		||||
        {
 | 
			
		||||
            return new ServiceInstanceListener[]
 | 
			
		||||
            {
 | 
			
		||||
                new ServiceInstanceListener(serviceContext =>
 | 
			
		||||
                    new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
 | 
			
		||||
                    {
 | 
			
		||||
                        Console.WriteLine($"Starting Kestrel on {url}");
 | 
			
		||||
                        ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");
 | 
			
		||||
 | 
			
		||||
                        return new WebHostBuilder()
 | 
			
		||||
                                    .UseKestrel()
 | 
			
		||||
                                    .ConfigureServices(
 | 
			
		||||
                                        services => services
 | 
			
		||||
                                            .AddSingleton<StatelessServiceContext>(serviceContext))
 | 
			
		||||
                                    .UseContentRoot(Directory.GetCurrentDirectory())
 | 
			
		||||
                                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
 | 
			
		||||
                                    .UseStartup<Startup>()
 | 
			
		||||
                                    .UseUrls(url)
 | 
			
		||||
                                    .ConfigureLogging((hostingContext, logging) =>
 | 
			
		||||
                                    {
 | 
			
		||||
                                        logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
 | 
			
		||||
                                        logging.AddConsole();
 | 
			
		||||
                                    })
 | 
			
		||||
                                    .Build();
 | 
			
		||||
                    }))
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,44 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
 | 
			
		||||
namespace OcelotApplicationService.Controllers
 | 
			
		||||
{
 | 
			
		||||
    [Route("api/[controller]")]
 | 
			
		||||
    public class ValuesController : Controller
 | 
			
		||||
    {
 | 
			
		||||
        // GET api/values
 | 
			
		||||
        [HttpGet]
 | 
			
		||||
        public IEnumerable<string> Get()
 | 
			
		||||
        {
 | 
			
		||||
            return new string[] { "value1", "value2" };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // GET api/values/5
 | 
			
		||||
        [HttpGet("{id}")]
 | 
			
		||||
        public string Get(int id)
 | 
			
		||||
        {
 | 
			
		||||
            return "value";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // POST api/values
 | 
			
		||||
        [HttpPost]
 | 
			
		||||
        public void Post([FromBody]string value)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // PUT api/values/5
 | 
			
		||||
        [HttpPut("{id}")]
 | 
			
		||||
        public void Put(int id, [FromBody]string value)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // DELETE api/values/5
 | 
			
		||||
        [HttpDelete("{id}")]
 | 
			
		||||
        public void Delete(int id)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,21 @@
 | 
			
		||||
<Project Sdk="Microsoft.NET.Sdk">
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <Description>Stateless Service Application</Description>
 | 
			
		||||
    <Authors> </Authors>
 | 
			
		||||
    <OutputType>Exe</OutputType>
 | 
			
		||||
    <TargetFramework>netcoreapp2.0</TargetFramework>
 | 
			
		||||
    <AssemblyName>OcelotApplicationService</AssemblyName>
 | 
			
		||||
    <PackageId>OcelotApplicationService</PackageId>
 | 
			
		||||
    <PackageTargetFallback>$(PackageTargetFallback)</PackageTargetFallback>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="Microsoft.ServiceFabric" Version="6.1.456"/>
 | 
			
		||||
    <PackageReference Include="Microsoft.ServiceFabric.Services" Version="3.0.456"/>
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore" Version="2.0.1"/>
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.2"/>
 | 
			
		||||
    <PackageReference Include="Microsoft.ServiceFabric.AspNetCore.Kestrel" Version="3.0.456"/>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
</Project>
 | 
			
		||||
@@ -0,0 +1,38 @@
 | 
			
		||||
using Microsoft.ServiceFabric.Services.Runtime;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace OcelotApplicationService
 | 
			
		||||
{
 | 
			
		||||
    internal static class Program
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This is the entry point of the service host process.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static void Main()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                // The ServiceManifest.XML file defines one or more service type names.
 | 
			
		||||
                // Registering a service maps a service type name to a .NET type.
 | 
			
		||||
                // When Service Fabric creates an instance of this service type,
 | 
			
		||||
                // an instance of the class is created in this host process.
 | 
			
		||||
 | 
			
		||||
                ServiceRuntime.RegisterServiceAsync("OcelotApplicationServiceType",
 | 
			
		||||
                    context => new ApiGateway(context)).GetAwaiter().GetResult();
 | 
			
		||||
 | 
			
		||||
                ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(ApiGateway).Name);
 | 
			
		||||
 | 
			
		||||
                // Prevents this host process from terminating so services keeps running. 
 | 
			
		||||
                Thread.Sleep(Timeout.Infinite);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString());
 | 
			
		||||
                throw;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,189 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics.Tracing;
 | 
			
		||||
using System.Fabric;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace OcelotApplicationService
 | 
			
		||||
{
 | 
			
		||||
    [EventSource(Name = "MyCompany-ServiceOcelotApplication-OcelotService")]
 | 
			
		||||
    internal sealed class ServiceEventSource : EventSource
 | 
			
		||||
    {
 | 
			
		||||
        public static readonly ServiceEventSource Current = new ServiceEventSource();
 | 
			
		||||
 | 
			
		||||
        static ServiceEventSource()
 | 
			
		||||
        {
 | 
			
		||||
            // A workaround for the problem where ETW activities do not get tracked until Tasks infrastructure is initialized.
 | 
			
		||||
            // This problem will be fixed in .NET Framework 4.6.2.
 | 
			
		||||
            Task.Run(() => { });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Instance constructor is private to enforce singleton semantics
 | 
			
		||||
        private ServiceEventSource() : base() { }
 | 
			
		||||
 | 
			
		||||
        #region Keywords
 | 
			
		||||
        // Event keywords can be used to categorize events. 
 | 
			
		||||
        // Each keyword is a bit flag. A single event can be associated with multiple keywords (via EventAttribute.Keywords property).
 | 
			
		||||
        // Keywords must be defined as a public class named 'Keywords' inside EventSource that uses them.
 | 
			
		||||
        public static class Keywords
 | 
			
		||||
        {
 | 
			
		||||
            public const EventKeywords Requests = (EventKeywords)0x1L;
 | 
			
		||||
            public const EventKeywords ServiceInitialization = (EventKeywords)0x2L;
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Events
 | 
			
		||||
        // Define an instance method for each event you want to record and apply an [Event] attribute to it.
 | 
			
		||||
        // The method name is the name of the event.
 | 
			
		||||
        // Pass any parameters you want to record with the event (only primitive integer types, DateTime, Guid & string are allowed).
 | 
			
		||||
        // Each event method implementation should check whether the event source is enabled, and if it is, call WriteEvent() method to raise the event.
 | 
			
		||||
        // The number and types of arguments passed to every event method must exactly match what is passed to WriteEvent().
 | 
			
		||||
        // Put [NonEvent] attribute on all methods that do not define an event.
 | 
			
		||||
        // For more information see https://msdn.microsoft.com/en-us/library/system.diagnostics.tracing.eventsource.aspx
 | 
			
		||||
 | 
			
		||||
        [NonEvent]
 | 
			
		||||
        public void Message(string message, params object[] args)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.IsEnabled())
 | 
			
		||||
            {
 | 
			
		||||
                string finalMessage = string.Format(message, args);
 | 
			
		||||
                Message(finalMessage);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private const int MessageEventId = 1;
 | 
			
		||||
        [Event(MessageEventId, Level = EventLevel.Informational, Message = "{0}")]
 | 
			
		||||
        public void Message(string message)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.IsEnabled())
 | 
			
		||||
            {
 | 
			
		||||
                WriteEvent(MessageEventId, message);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [NonEvent]
 | 
			
		||||
        public void ServiceMessage(ServiceContext serviceContext, string message, params object[] args)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.IsEnabled())
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
                string finalMessage = string.Format(message, args);
 | 
			
		||||
                ServiceMessage(
 | 
			
		||||
                    serviceContext.ServiceName.ToString(),
 | 
			
		||||
                    serviceContext.ServiceTypeName,
 | 
			
		||||
                    GetReplicaOrInstanceId(serviceContext),
 | 
			
		||||
                    serviceContext.PartitionId,
 | 
			
		||||
                    serviceContext.CodePackageActivationContext.ApplicationName,
 | 
			
		||||
                    serviceContext.CodePackageActivationContext.ApplicationTypeName,
 | 
			
		||||
                    serviceContext.NodeContext.NodeName,
 | 
			
		||||
                    finalMessage);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // For very high-frequency events it might be advantageous to raise events using WriteEventCore API.
 | 
			
		||||
        // This results in more efficient parameter handling, but requires explicit allocation of EventData structure and unsafe code.
 | 
			
		||||
        // To enable this code path, define UNSAFE conditional compilation symbol and turn on unsafe code support in project properties.
 | 
			
		||||
        private const int ServiceMessageEventId = 2;
 | 
			
		||||
        [Event(ServiceMessageEventId, Level = EventLevel.Informational, Message = "{7}")]
 | 
			
		||||
        private
 | 
			
		||||
#if UNSAFE
 | 
			
		||||
        unsafe
 | 
			
		||||
#endif
 | 
			
		||||
        void ServiceMessage(
 | 
			
		||||
            string serviceName,
 | 
			
		||||
            string serviceTypeName,
 | 
			
		||||
            long replicaOrInstanceId,
 | 
			
		||||
            Guid partitionId,
 | 
			
		||||
            string applicationName,
 | 
			
		||||
            string applicationTypeName,
 | 
			
		||||
            string nodeName,
 | 
			
		||||
            string message)
 | 
			
		||||
        {
 | 
			
		||||
#if !UNSAFE
 | 
			
		||||
            WriteEvent(ServiceMessageEventId, serviceName, serviceTypeName, replicaOrInstanceId, partitionId, applicationName, applicationTypeName, nodeName, message);
 | 
			
		||||
#else
 | 
			
		||||
            const int numArgs = 8;
 | 
			
		||||
            fixed (char* pServiceName = serviceName, pServiceTypeName = serviceTypeName, pApplicationName = applicationName, pApplicationTypeName = applicationTypeName, pNodeName = nodeName, pMessage = message)
 | 
			
		||||
            {
 | 
			
		||||
                EventData* eventData = stackalloc EventData[numArgs];
 | 
			
		||||
                eventData[0] = new EventData { DataPointer = (IntPtr) pServiceName, Size = SizeInBytes(serviceName) };
 | 
			
		||||
                eventData[1] = new EventData { DataPointer = (IntPtr) pServiceTypeName, Size = SizeInBytes(serviceTypeName) };
 | 
			
		||||
                eventData[2] = new EventData { DataPointer = (IntPtr) (&replicaOrInstanceId), Size = sizeof(long) };
 | 
			
		||||
                eventData[3] = new EventData { DataPointer = (IntPtr) (&partitionId), Size = sizeof(Guid) };
 | 
			
		||||
                eventData[4] = new EventData { DataPointer = (IntPtr) pApplicationName, Size = SizeInBytes(applicationName) };
 | 
			
		||||
                eventData[5] = new EventData { DataPointer = (IntPtr) pApplicationTypeName, Size = SizeInBytes(applicationTypeName) };
 | 
			
		||||
                eventData[6] = new EventData { DataPointer = (IntPtr) pNodeName, Size = SizeInBytes(nodeName) };
 | 
			
		||||
                eventData[7] = new EventData { DataPointer = (IntPtr) pMessage, Size = SizeInBytes(message) };
 | 
			
		||||
 | 
			
		||||
                WriteEventCore(ServiceMessageEventId, numArgs, eventData);
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private const int ServiceTypeRegisteredEventId = 3;
 | 
			
		||||
        [Event(ServiceTypeRegisteredEventId, Level = EventLevel.Informational, Message = "Service host process {0} registered service type {1}", Keywords = Keywords.ServiceInitialization)]
 | 
			
		||||
        public void ServiceTypeRegistered(int hostProcessId, string serviceType)
 | 
			
		||||
        {
 | 
			
		||||
            WriteEvent(ServiceTypeRegisteredEventId, hostProcessId, serviceType);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private const int ServiceHostInitializationFailedEventId = 4;
 | 
			
		||||
        [Event(ServiceHostInitializationFailedEventId, Level = EventLevel.Error, Message = "Service host initialization failed", Keywords = Keywords.ServiceInitialization)]
 | 
			
		||||
        public void ServiceHostInitializationFailed(string exception)
 | 
			
		||||
        {
 | 
			
		||||
            WriteEvent(ServiceHostInitializationFailedEventId, exception);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // A pair of events sharing the same name prefix with a "Start"/"Stop" suffix implicitly marks boundaries of an event tracing activity.
 | 
			
		||||
        // These activities can be automatically picked up by debugging and profiling tools, which can compute their execution time, child activities,
 | 
			
		||||
        // and other statistics.
 | 
			
		||||
        private const int ServiceRequestStartEventId = 5;
 | 
			
		||||
        [Event(ServiceRequestStartEventId, Level = EventLevel.Informational, Message = "Service request '{0}' started", Keywords = Keywords.Requests)]
 | 
			
		||||
        public void ServiceRequestStart(string requestTypeName)
 | 
			
		||||
        {
 | 
			
		||||
            WriteEvent(ServiceRequestStartEventId, requestTypeName);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private const int ServiceRequestStopEventId = 6;
 | 
			
		||||
        [Event(ServiceRequestStopEventId, Level = EventLevel.Informational, Message = "Service request '{0}' finished", Keywords = Keywords.Requests)]
 | 
			
		||||
        public void ServiceRequestStop(string requestTypeName, string exception = "")
 | 
			
		||||
        {
 | 
			
		||||
            WriteEvent(ServiceRequestStopEventId, requestTypeName, exception);
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Private methods
 | 
			
		||||
        private static long GetReplicaOrInstanceId(ServiceContext context)
 | 
			
		||||
        {
 | 
			
		||||
            StatelessServiceContext stateless = context as StatelessServiceContext;
 | 
			
		||||
            if (stateless != null)
 | 
			
		||||
            {
 | 
			
		||||
                return stateless.InstanceId;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            StatefulServiceContext stateful = context as StatefulServiceContext;
 | 
			
		||||
            if (stateful != null)
 | 
			
		||||
            {
 | 
			
		||||
                return stateful.ReplicaId;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            throw new NotSupportedException("Context type not supported.");
 | 
			
		||||
        }
 | 
			
		||||
#if UNSAFE
 | 
			
		||||
        private int SizeInBytes(string s)
 | 
			
		||||
        {
 | 
			
		||||
            if (s == null)
 | 
			
		||||
            {
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return (s.Length + 1) * sizeof(char);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,40 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
using Microsoft.Extensions.Configuration;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
using Microsoft.Extensions.Options;
 | 
			
		||||
 | 
			
		||||
namespace OcelotApplicationService
 | 
			
		||||
{
 | 
			
		||||
    public class Startup
 | 
			
		||||
    {
 | 
			
		||||
        public Startup(IConfiguration configuration)
 | 
			
		||||
        {
 | 
			
		||||
            Configuration = configuration;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IConfiguration Configuration { get; }
 | 
			
		||||
 | 
			
		||||
        // This method gets called by the runtime. Use this method to add services to the container.
 | 
			
		||||
        public void ConfigureServices(IServiceCollection services)
 | 
			
		||||
        {
 | 
			
		||||
            services.AddMvc();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
 | 
			
		||||
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
 | 
			
		||||
        {
 | 
			
		||||
            if (env.IsDevelopment())
 | 
			
		||||
            {
 | 
			
		||||
                app.UseDeveloperExceptionPage();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            app.UseMvc();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								samples/OcelotServiceFabric/src/global.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								samples/OcelotServiceFabric/src/global.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "projects": [ "../"],
 | 
			
		||||
  "sdk": {
 | 
			
		||||
    "version": "2.1.4"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user