Перенос узла службы (по протоколу TCP, не через Веб) с .NET Framework 4.8 на .NET Core 3.1

#c# #web-services #.net-core #hosting #nettcpbinding

Вопрос:

Я переношу этот узел службы (по протоколу TCP, не через Веб) с .NET Framework 4.8 на .NET Core 3.1:

 using (this._host = new ServiceHost(_receiver, new Uri("net.tcp://localhost:8065")))
{
    this._host.OpenTimeout = TimeSpan.FromMinutes(5);
    this._host.CloseTimeout = TimeSpan.FromMinutes(5);

    var binding = new NetTcpBinding
    {
        CloseTimeout = TimeSpan.FromSeconds(15),
        OpenTimeout = TimeSpan.FromSeconds(15),
        SendTimeout = TimeSpan.FromSeconds(15),
        ReceiveTimeout = TimeSpan.FromSeconds(15);
    };

    this._host.AddServiceEndpoint(typeof(IMessageReceiver), binding, "ISubscribe"); 
}   
 

Но нет канала, чтобы попасть в этот момент (старый код в .NET Framework 4.8):

 
 [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single,
 IncludeExceptionDetailInFaults = true)]  
    public class MessageReceiver : IMessageReceiver
    {
        ...
        
        public bool Subscribe()
        {
            try
            { 
                IMessageSender callback = OperationContext.Current.GetCallbackChannel<IMessageSender>();
                if (!_subscribers.Contains(callback))
                {               
                    _subscribers.Add(callback);
                    Console.WriteLine("Subscriber");
                }
                return true;
            }
            catch (Exception e)
            {
                Console.WriteLine("Subscribe Exception"   e.ToString());
                return false;
            }
        }
        
        ...
    }

 

И я не могу перенести эту конфигурацию в .NET Core:

 
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single,
 IncludeExceptionDetailInFaults = true)]  
 
 

Я пытаюсь справиться с этим:

 public static IWebHostBuilder CreateHostBuilder(string[] args) =>
 WebHost.CreateDefaultBuilder(args)  
 .ConfigureServices(services =>
 {  
    services.AddMessageReceiverFramework(new IPEndPoint(IPAddress.Any, 8065));          
 })
 .UseUrls("net.tcp://localhost:8065/ISubscribe")           
 .UseStartup<Startup>(); 

public static class MessageReceiverExtensionsAux
{
    public static IServiceCollection AddMessageReceiverFramework(this IServiceCollection services,
 IPEndPoint endPoint)
    {
        services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<KestrelServerOptions>,
MessageReceiverOptionsSetup>());

        services.Configure<MessageReceiverOptions>(o =>
        {
            o.EndPoint = endPoint;
        });
        services.TryAddSingleton<IMessageReceiver, MessageReceiver>();

        return services;
    }
}
 

Я ищу лучшую стратегию для улучшения того же поведения на стороне клиента (.NET Framework 4.8).

Есть какие-нибудь предложения?

Большое спасибо.

Комментарии:

1. Есть какие-нибудь предложения? Что будет до тех пор, пока CoreWCF не станет пригодным для использования или не будет придерживаться фреймворка 4.8 … Хотя в .net core есть поддержка клиентов для WCF (для некоторых привязок), официальной поддержки хостинга нет

Ответ №1:

У меня есть CoreWCF.Http-пакет: https://github.com/CoreWCF/CoreWCF

    using CoreWCF; 
   using CoreWCF.Configuration;

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
     WebHost.CreateDefaultBuilder(args)
     .ConfigureServices(services =>
     {
        ...        
        
     }).UseKestrel(options => {
         
         options.ListenLocalhost(8080);
       
     }).UseNetTcp(8808)
       .UseStartup<Startup>();
     

    public class Startup
    {             
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddServiceModelServices();                            
        }
        public void Configure(IApplicationBuilder app, IHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseServiceModel(builder =>
            {
                var bind = new NetTcpBinding(); 
                 
                builder
                .AddService<MessageReceiver>()
                .AddServiceEndpoint<MessageReceiver>(typeof(IMessageReceiver),bind, "/nettcp");                    
            });                             
        }
    }
 

Не реализован дуплексный канал. Но это хорошо для меня, с новым кодом для этого неудобства.