Що замінює WCF у .Net Core?


97

Я звик створювати консольний додаток .Net Framework і виставляти Add(int x, int y)функції через службу WCF з нуля за допомогою бібліотеки класів (.Net Framework). Потім я використовую консольний додаток для виклику цієї функції через сервер.

Однак якщо я використовую програму Console (.Net Core) та бібліотеку класів (.Net Core), System.ServiceModel недоступний. Я кілька разів гуглив, але не з'ясував, що "замінює" WCF у цьому випадку.

Як виставити Add(int x, int y)функцію в бібліотеці класів консольному додатку всередині .Net Core? Я бачу System.ServiceModel.Web, і оскільки це намагається бути крос-платформенним, чи потрібно мені створювати службу RESTful?


do I have to create a RESTful service?- AFAIK так (або скористайтеся яким-небудь іншим рішенням, якого я б не знав для .NET Core)
Крістоф Фінк

3
WCF, швидше за все, не буде перенесено на .NET Core, оскільки більша частина кодової бази залежить від внутрішніх бібліотек Windows. Чи можете ви використовувати ASP.NET Core? Там у вас буде HTTP-сервер, який легко крос-платформенний
Каміло Теревінто,

2
Клієнтська сторона WCF вже підтримується (не знаю, скільки), серверна - це гаряче обговорюваний та проголосований запит функції.
Хенк Холтерман

Здається, Visual Studio 2017 15.5 і пізніші версії підтримують генерацію класів проксі-сервер .NET Core . Також є список підтримуваних функцій .
jamiebarrow

5
Коротше: CoreWCF
Димитров

Відповіді:


35

WCF не підтримується в .NET Core, оскільки це специфічна для Windows технологія, і .NET Core повинен бути міжплатформенним.

Якщо ви впроваджуєте міжпроцесорне спілкування, спробуйте спробувати проект IpcServiceFramework .

Це дозволяє створювати послуги у стилі WCF наступним чином:

  1. Створити контракт на обслуговування

    public interface IComputingService
    {
        float AddFloat(float x, float y);
    }
    
  2. Впровадити послугу

    class ComputingService : IComputingService
    {
        public float AddFloat(float x, float y)
        {
            return x + y;
        }
    }
    
  3. Розмістіть службу в додатку Console

    class Program
    {
        static void Main(string[] args)
        {
            // configure DI
            IServiceCollection services = ConfigureServices(new ServiceCollection());
    
            // build and run service host
            new IpcServiceHostBuilder(services.BuildServiceProvider())
                .AddNamedPipeEndpoint<IComputingService>(name: "endpoint1", pipeName: "pipeName")
                .AddTcpEndpoint<IComputingService>(name: "endpoint2", ipEndpoint: IPAddress.Loopback, port: 45684)
                .Build()
                .Run();
        }
    
        private static IServiceCollection ConfigureServices(IServiceCollection services)
        {
            return services
                .AddIpc()
                .AddNamedPipe(options =>
                {
                    options.ThreadCount = 2;
                })
                .AddService<IComputingService, ComputingService>();
        }
    }
    
  4. Виклик послуги з клієнтського процесу

    IpcServiceClient<IComputingService> client = new IpcServiceClientBuilder<IComputingService>()
        .UseNamedPipe("pipeName") // or .UseTcp(IPAddress.Loopback, 45684) to invoke using TCP
        .Build();
    
    float result = await client.InvokeAsync(x => x.AddFloat(1.23f, 4.56f));
    

3
Приємно! Можливо, варто оновити, щоб скористатися перевагами .Net core system.io.pipelines blogs.msdn.microsoft.com/dotnet/2018/07/09/…
Sigex,

Вибачте, мені тут не вистачає чогось важливого? Хіба труби не повинні бути призначені лише для того самого хост-зв'язку?
user1034912

2
Так, вам не вистачає того, що це коротко демонструє, що IpcServiceFramework, як і WCF, дозволяє безперешкодно перемикатися між різними технологіями обміну повідомленнями.
Кріс Ф Керролл,

4
WCF можна вважати вікнами, характерними для деяких протоколів, які він абстрагує, але служби SOAP - ні. Як створити веб-службу SOAP у ядрі .net?
Джеремі

3
Примітка: автор цього проекту написав такий коментар: "Хлопці, я особисто не маю часу підтримувати цей проект через кілька місяців. Тим часом .NET Core 3.0 випущений із функцією gRPC." ( github.com/jacqueskang/IpcServiceFramework/issues/… ). Дивіться другу відповідь щодо gRPC.
gerard

64

Ви можете використовувати gRPC для розміщення веб-служб всередині основного додатка .NET.

введіть тут опис зображення

Вступ

  1. gRPC - це високопродуктивна платформа RPC з відкритим кодом, спочатку розроблена Google.
  2. Структура базується на моделі клієнт-сервер віддалених викликів процедур. Клієнтська програма може безпосередньо викликати методи серверної програми, ніби це локальний об'єкт.

Приклад

Код сервера

class Program
{
    static void Main(string[] args)
    {
        RunAsync().Wait();
    }

    private static async Task RunAsync()
    {
        var server = new Grpc.Core.Server
        {
            Ports = { { "127.0.0.1", 5000, ServerCredentials.Insecure } },
            Services =
            {
                ServerServiceDefinition.CreateBuilder()
                    .AddMethod(Descriptors.Method, async (requestStream, responseStream, context) =>
                    {
                        await requestStream.ForEachAsync(async additionRequest =>
                        {
                            Console.WriteLine($"Recieved addition request, number1 = {additionRequest.X} --- number2 = {additionRequest.Y}");
                            await responseStream.WriteAsync(new AdditionResponse {Output = additionRequest.X + additionRequest.Y});
                        });
                    })
                    .Build()
            }
        };

        server.Start();

        Console.WriteLine($"Server started under [127.0.0.1:5000]. Press Enter to stop it...");
        Console.ReadLine();

        await server.ShutdownAsync();
    }
}

Код клієнта

class Program
{
    static void Main(string[] args)
    {
        RunAsync().Wait();
    }

    private static async Task RunAsync()
    {
        var channel = new Channel("127.0.0.1", 5000, ChannelCredentials.Insecure);
        var invoker = new DefaultCallInvoker(channel);
        using (var call = invoker.AsyncDuplexStreamingCall(Descriptors.Method, null, new CallOptions{}))
        {
            var responseCompleted = call.ResponseStream
                .ForEachAsync(async response => 
                {
                    Console.WriteLine($"Output: {response.Output}");
                });

            await call.RequestStream.WriteAsync(new AdditionRequest { X = 1, Y = 2});
            Console.ReadLine();

            await call.RequestStream.CompleteAsync();
            await responseCompleted;
        }

        Console.WriteLine("Press enter to stop...");
        Console.ReadLine();

        await channel.ShutdownAsync();
    }
}

Спільні класи між клієнтом та сервером

[Schema]
public class AdditionRequest
{
    [Id(0)]
    public int X { get; set; }
    [Id(1)]
    public int Y { get; set; }
}

[Schema]
public class AdditionResponse
{
    [Id(0)]
    public int Output { get; set; }
}

Дескриптори послуг

using Grpc.Core;
public class Descriptors
{
    public static Method<AdditionRequest, AdditionResponse> Method =
            new Method<AdditionRequest, AdditionResponse>(
                type: MethodType.DuplexStreaming,
                serviceName: "AdditonService",
                name: "AdditionMethod",
                requestMarshaller: Marshallers.Create(
                    serializer: Serializer<AdditionRequest>.ToBytes,
                    deserializer: Serializer<AdditionRequest>.FromBytes),
                responseMarshaller: Marshallers.Create(
                    serializer: Serializer<AdditionResponse>.ToBytes,
                    deserializer: Serializer<AdditionResponse>.FromBytes));
}

Серіалізатор / десериалізатор

public static class Serializer<T>
{
    public static byte[] ToBytes(T obj)
    {
        var buffer = new OutputBuffer();
        var writer = new FastBinaryWriter<OutputBuffer>(buffer);
        Serialize.To(writer, obj);
        var output = new byte[buffer.Data.Count];
        Array.Copy(buffer.Data.Array, 0, output, 0, (int)buffer.Position);
        return output;
    }

    public static T FromBytes(byte[] bytes)
    {
        var buffer = new InputBuffer(bytes);
        var data = Deserialize<T>.From(new FastBinaryReader<InputBuffer>(buffer));
        return data;
    }
}

Вихідні дані

Зразок вихідних даних клієнта

Зразок вихідних даних сервера

Список літератури

  1. https://blogs.msdn.microsoft.com/dotnet/2018/12/04/announcing-net-core-3-preview-1-and-open-sourcing-windows-desktop-frameworks/
  2. https://grpc.io/docs/
  3. https://grpc.io/docs/quickstart/csharp.html
  4. https://github.com/grpc/grpc/tree/master/src/csharp

Тести

  1. http://csharptest.net/787/benchmarking-wcf-compared-to-rpclibrary/index.html

7
Станом на березень 2019 року ця відповідь є більш актуальною. Див. Github.com/grpc/grpc-dotnet (та оновлення ASP.NET Core у .NET Core 3.0 ).
реснянський

1
Я думаю, що це найближча відповідь, але, на жаль, вона не забезпечує жодної поведінки та підтримки.
Джо

4
Також майте на увазі, що на даний момент gRPCне компілюється проти ланцюжка власних інструментів .net у VS 2019 (16.0.2) і, отже, не буде працювати з UWP.
Самуїл,

2
Якщо ви шукаєте підтримку іменованої труби, я написав транспорт gRPC
Cyanfish

1
Зауважте, що (станом на 06.04.2020) grpc-dotnet не має пакетів для ARM.
GafferMan2112

23

Схоже, буде створений проект CoreWCF, який підтримує .NET Foundation за підтримки Microsoft.

Детальніше у вітанні Core WCF до .NET Foundation

Спочатку буде застосовано лише транспорт netTcp та http.


Це оманлива відповідь. Microsoft перенесла лише клієнт wcf. Хост або сервісний хост Wcf недоступні, і вони не мають наміру це робити. Я навчився цього важким шляхом. gRPC - це шлях
user1034912

@ user1034912 Ви не праві. CoreWCF - це легкий сервер WCF, який переноситься на ядро ​​.NET. Він має обмеження, але в деяких випадках це хороший вибір.
Доступ заборонено

Так, лише якщо ви клієнт-споживач, реалізація
сервісу

@ user1034912 Ні, сторона сервера доступна. github.com/CoreWCF/CoreWCF/blob/master/src/Samples/…
доступ відмовлено


9

WCF робить багато речей; це простий спосіб віддалених викликів процедур між двома програмами (процесами) на одній машині, використовуючи іменовані канали; це може бути великий внутрішній канал зв'язку клієнт-сервер між компонентами .NET, використовуючи двійкову серіалізацію через TCPIP; або він може забезпечити стандартизований крос-технологічний API, наприклад, через SOAP. Він навіть підтримує такі речі, як асинхронні повідомлення, через MSMQ.

Для .NET Core існують різні заміни залежно від призначення.

Для крос-платформного API ви б замінили це на службу REST за допомогою ASP.NET.

Для міжпроцесорних з’єднань або підключення клієнт-сервер добре підійде gRPC із чудовою відповіддю, яку дасть @Gopi.

Тож відповідь на питання "Що замінює WCF" залежить від того, для чого ви його використовуєте.


5

Існує репозитарій спільноти https://github.com/CoreWCF/CoreWCF, який реалізує деякі частини WCF. Ви можете використовувати його для підтримки деяких простих служб WCF. Однак не всі функції підтримуються.


4

Отже, з мого дослідження, найкращим рішенням не є автоматично згенеровані класи проксі. Найкращим рішенням є створення служби RESTful та серіалізація тіла відповіді на модельні об'єкти. Де моделі - це звичайні об’єкти моделей, знайдені в шаблоні проектування MVC.

Дякуємо за ваші відповіді



Так, я хотів це автоматично згенеровані проксі-класи. Я використовую RESTful сервіси / RPC для цієї функції
Sigex

Це репо лише для клієнтських бібліотек
orellabac

Restful не підтримує дуплексний зв’язок
user1034912

1

Ви також можете самостійно розмістити веб-API ASP.NET Core.

<!-- SelfHosted.csproj -->
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <!-- see: https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.1&tabs=visual-studio#framework-reference -->
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.0" />
  </ItemGroup>

</Project>
// Program.cs
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace SelfHosted
{
    class Program
    {
        static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            // see: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-3.1
            return Host.CreateDefaultBuilder(args)
                .ConfigureHostConfiguration(configHost =>
                {
                    configHost.SetBasePath(Directory.GetCurrentDirectory());
                    configHost.AddJsonFile("appsettings.json", optional: true);
                    configHost.AddEnvironmentVariables(prefix: "SelfHosted_");
                    configHost.AddCommandLine(args);
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.CaptureStartupErrors(true);
                    webBuilder.UseStartup<Startup>();
                });
        }
    }
}
// Startup.cs
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace SelfHosted
{
    public class Startup
    {
        public Startup(IConfiguration configuration, IWebHostEnvironment env)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            // see: https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/web-api/index/samples/3.x
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}
// Controllers\TestController.cs
using System.Net.Mime;
using Microsoft.AspNetCore.Mvc;

namespace SelfHosted.Controllers
{
    [ApiController]
    [Produces(MediaTypeNames.Application.Json)]
    [Route("[controller]")]
    public class HelloController : SelfHostedControllerBase
    {
        [HttpGet]
        public ActionResult<string> HelloWorld() => "Hello World!";

        [HttpGet("{name}")]
        public ActionResult<string> HelloName(string name) => $"Hello {name}!";
    }
}

Asp core web api не підтримує дуплексний зв’язок на одному порту, як це робить wcf.
user1034912

0

Доступний порт .NET Core: https://github.com/dotnet/wcf Він все ще знаходиться в попередньому перегляді, але вони активно його розробляють.


14
Я вважаю, що цей порт призначений для зв'язку від Core до WCF, але не для написання WCF в Core.
hal9000

7
У зв’язаному сховищі github чітко сказано: "Це репозиторій містить орієнтовані на клієнта бібліотеки WCF, які дозволяють додаткам, побудованим на .NET Core, взаємодіяти зі службами WCF".
Bahaa,

0

Як сьогодні всі доступні WCFCore selfhost не так просто встановити та використовувати.
Найкращими для HostedService будуть альтернативи, як показав gRPC у попередній відповіді, і зауважте, що за 1 рік можна багато чого змінити, впевнений, що WCF підтримується в Core лише як клієнт, який працює нормально.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.