.NET Framework で CoreWCF を使ってみた

.NET FrameworkWCF サービスの .NET 8 移行を検討しているけど、推奨されている gRPC はほぼ実装し直しになるので現実的に難しい。CoreWCF ならまだ可能性あるか?

CoreWCF は .NET Standard 2.0 サポートしているので、.NET Framework でも動かせるはず。CoreWCF に移行してから .NET 8 に移行する作戦ならいけるかも。

www.nuget.org

ひとまず .NET Framework で CoreWCF が動くことを確認しなければ。.NET Framework で動く ASP.NET Core は 2.2。新規作成のテンプレートはもう無い。csproj ファイルを直接編集するしかなかった。

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net48</TargetFramework>
      <OutputType>exe</OutputType>
  </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="CoreWCF.NetTcp" Version="1.5.2" />
        <PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
    </ItemGroup>
</Project>

CoreWCF を使ってサービスを実装。NetTcpBinding を使う場合、UseNetTcp の呼び出しが必要だった。これ書いてなくて、クライアントから全然繋がらなくて1時間くらい嵌った。

using CoreWCF;
using CoreWCF.Configuration;
using HelloCoreWcf.Shared;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;

namespace HelloCoreWcf.Shared
{
    [ServiceContract]
    public interface IGreetingService
    {
        [OperationContract]
        string Hello(string name);
    }
}

namespace HelloCoreWcf
{
    class Program
    {
        static void Main(string[] args)
        {
            var host = WebHost.CreateDefaultBuilder<Startup>(args)
                .UseNetTcp(808) // TCP を使う
                .Build();
            host.Run();
        }
    }

    class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddServiceModelServices();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseServiceModel(builder =>
            {
                builder.AddService<GreetingService>();

                // NetTcpBinding を使う
                var binding = new NetTcpBinding();
                binding.Security.Mode = SecurityMode.None;
                builder.AddServiceEndpoint<GreetingService, IGreetingService>(
                    binding: binding,
                    address: "/GreetingService");
            });
        }
    }

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

クライアント側は、.NET Framework のコンソールアプリケーション。WCF サービスの呼び出しには、従来通り System.ServiceModel をアセンブリ参照して使っている。

using System;
using System.ServiceModel;

namespace HelloCoreWcf.Shared
{
    [ServiceContract]
    public interface IGreetingService
    {
        [OperationContract]
        string Hello(string name);
    }
}

namespace HelloCoreWcf.Client
{
    using System.ServiceModel.Channels;
    using Shared;

    internal class Program
    {
        static void Main(string[] args)
        {
            var binding = new NetTcpBinding();
            binding.Security.Mode = SecurityMode.None;
            var address = "net.tcp://localhost:808/GreetingService";
            var channel = ChannelFactory<IGreetingService>.CreateChannel(
                binding: binding,
                endpointAddress: new EndpointAddress(address));

            var result = channel.Hello("Kubo");
            Console.WriteLine(result);

            ((IChannel)channel).Close();
            Console.ReadLine();
        }
    }
}

実行結果は次の通り。.NET Framework でも CoreWCF 使って WCF サービスを実装できたし、WCF クライアントからもちゃんと呼び出せた。

実際のアプリでは、WCF の結構ディープな機能を使っているので、それらがすべて CoreWCF に移行できるかを試す必要があるな。