Что заменяет WCF в .Net Core?

96

Я привык создавать консольное приложение .Net Framework и предоставлять Add(int x, int y)функцию через службу WCF с нуля с помощью библиотеки классов (.Net Framework). Затем я использую консольное приложение для прокси-вызова этой функции на сервере.

Однако, если я использую консольное приложение (.Net Core) и библиотеку классов (.Net Core), System.ServiceModel недоступен. Я немного погуглил, но не понял, что «заменяет» WCF в этом случае.

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

Sigex
источник
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. Разместите службу в консольном приложении

    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 system.io.pipelines blogs.msdn.microsoft.com/dotnet/2018/07/09/…
Sigex
Извините, я упустил здесь что-то важное? Разве каналы не должны использоваться только для связи с одним и тем же хостом?
user1034912 01
2
Да, вам не хватает того, что это кратко демонстрирует, что IpcServiceFramework, как и WCF, позволяет плавно переключаться между различными технологиями обмена сообщениями.
Крис Ф. Кэрролл
4
WCF может считаться специфичным для окон в некоторых протоколах, которые он абстрагирует, но службы SOAP - нет. Как создать веб-службу SOAP в ядре .NET?
Джереми
3
Примечание: автор этого проекта написал следующий комментарий: «Ребята, по личным причинам у меня нет времени поддерживать этот проект уже несколько месяцев. Между тем .NET Core 3.0 выпущен с функцией gRPC». ( github.com/jacqueskang/IpcServiceFramework/issues/… ). См. Второй ответ для gRPC.
Джерард
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
Я думаю, что это наиболее близкий ответ, но, к сожалению, он не обеспечивает никакого поведения или поддержки дросселирования.
joe
4
Также имейте в gRPCвиду, что на данный момент не компилируется с собственной цепочкой инструментов .net в VS 2019 (16.0.2) и, следовательно, не будет работать с UWP.
Самуэль
2
Если вам нужна поддержка именованных каналов, я написал транспорт gRPC: github.com/cyanfish/grpc-dotnet-
namedpipes
1
Обратите внимание, что (по состоянию на 06.04.2020) grpc-dotnet не имеет пакетов для ARM.
GafferMan2112,
23

Похоже, что будет проект CoreWCF, поддерживаемый .NET Foundation при поддержке Microsoft.

Дополнительные сведения см. В статье «Приветствие Core WCF в .NET Foundation».

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

Рафал Страшевский
источник
Это вводящий в заблуждение ответ. Microsoft только портировала клиент wcf. Хост wcf или хост службы недоступен, и они не собираются этого делать. Я усвоил это на собственном горьком опыте. gRPC
лучший вариант
@ 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.

Спасибо за ваши ответы

Sigex
источник
Да, мне нужны были автоматически сгенерированные прокси-классы. Я использую RESTful services / 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 Он все еще находится на стадии предварительной версии, но они активно его разрабатывают.

Flupp
источник
14
Я считаю, что этот порт предназначен для связи от Core к WCF, но не для написания WCF в Core.
hal9000
7
В связанном репозитории github четко сказано: «Этот репозиторий содержит клиент-ориентированные библиотеки WCF, которые позволяют приложениям, созданным на основе .NET Core, взаимодействовать со службами WCF».
Бахаа,
0

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

Хорхе Альварадо
источник