ASP.NET Core のホステッドサービスとして WCF サービスを動かす

ASP.NET Core には HostedService という機能があって、 バックグラウンドタスクなんかを実装するのに使えたりする。

docs.microsoft.com

上のドキュメントでは、そのものずばりバックグラウンドタスクを実装しているわけだけど、 WCF サービスも実行できるんじゃないかと思ったので試してみた。 なお、サーバーサイド WCF だから .NET Framework 限定。

using System.ServiceModel;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

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

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseUrls("http://localhost:8000")
                .UseStartup<Startup>();
    }

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddHostedService<WcfHostedService>();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Hello World!");
            });
        }
    }

    [ServiceContract(Namespace = "AspNetCoreWcf")]
    public interface IGreetingService
    {
        [OperationContract]
        string Greet(string name);
    }

    public class GreetingService : IGreetingService
    {
        public string Greet(string name)
        {
            return $"Hello, {name}.";
        }
    }

    public class WcfHostedService : Microsoft.Extensions.Hosting.IHostedService
    {
        readonly ServiceHost serviceHost;
        readonly ILogger<WcfHostedService> logger;

        public WcfHostedService(ILoggerFactory loggerFactory)
        {
            logger = loggerFactory.CreateLogger<WcfHostedService>();

            serviceHost = new ServiceHost(typeof(GreetingService));
            serviceHost.AddServiceEndpoint(
                typeof(IGreetingService),
                new NetTcpBinding(),
                "net.tcp://localhost:8080/GreetingService");
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            serviceHost.Open();
            logger.LogInformation($"WCF Service Started.");
            return Task.CompletedTask;
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            serviceHost.Close();
            logger.LogInformation($"WCF Service Stopped.");
            return Task.CompletedTask;
        }
    }
}

WCF サービスがホステッドサービスとして動いているか確認するために、 WCF クライアントを使ってアクセスしてみる。 WCF サービスだけでなく ASP.NET Core も動いているか、 こちらは HttpClient を使って確認。

using System;
using System.Net.Http;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Threading.Tasks;

namespace AspNetCoreWcfClient
{
    class Program
    {
        static void Main(string[] args)
        {
            MainAsync().GetAwaiter().GetResult();
            Console.ReadLine();
        }

        static async Task MainAsync()
        {
            var httpClient = new HttpClient();
            var aspNetCoreResult = await httpClient.GetStringAsync(
                "http://localhost:8000");
            Console.WriteLine($"ASP.NET Core: {aspNetCoreResult}");

            var channel = ChannelFactory<IGreetingService>.CreateChannel(
                new NetTcpBinding(),
                new EndpointAddress("net.tcp://localhost:8080/GreetingService"));
            var wcfResult = channel.Greet("Douan");
            Console.WriteLine($"WCF: {wcfResult}");
            ((IChannel)channel).Close();
        }
    }

    [ServiceContract(Namespace = "AspNetCoreWcf")]
    public interface IGreetingService
    {
        [OperationContract]
        string Greet(string name);
    }
}

ASP.NET Core と WCF サービス、どちらもちゃんとレスポンスを返してくれたので、 動いていることを確認できた。

f:id:griefworker:20190329105725p:plain

これが何の役に立つかといえば、ほとんどの人には役に立たないかもしれない。 ただ、世の中には WCF を捨てれない環境があったりするので…。 あぁ、WCF 捨てて gRPC とかに移りたい。