Apa yang menggantikan WCF di .Net Core?


97

Saya terbiasa membuat aplikasi konsol .Net Framework dan mengekspos Add(int x, int y)fungsi melalui layanan WCF dari awal dengan Class Library (.Net Framework). Saya kemudian menggunakan aplikasi konsol untuk memanggil proxy fungsi ini di dalam server.

Namun jika saya menggunakan Aplikasi Konsol (.Net Core) dan Perpustakaan Kelas (.Net Core) System.ServiceModel tidak tersedia. Saya telah melakukan beberapa Googling tetapi saya belum menemukan apa yang "menggantikan" WCF dalam hal ini.

Bagaimana cara saya mengekspos Add(int x, int y)fungsi dalam perpustakaan kelas ke aplikasi konsol semua dalam .Net Core? Saya melihat System.ServiceModel.Web, dan karena ini mencoba untuk menjadi lintas platform, apakah saya harus membuat layanan RESTful?


do I have to create a RESTful service?- AFAIK ya (atau gunakan beberapa solusi Pihak ke-3 yang tidak saya ketahui untuk .NET Core)
Christoph Fink

3
WCF kemungkinan tidak akan di-porting ke .NET Core, karena sebagian besar basis kode bergantung pada pustaka internal Windows. Bisakah Anda menggunakan ASP.NET Core? Di sana Anda akan memiliki server HTTP yang siap lintas platform
Camilo Terevinto

2
Sisi klien WCF sudah didukung (saya tidak tahu berapa banyak), sisi server adalah permintaan fitur yang diperdebatkan dengan hangat dan dipilih.
Henk Holterman

Tampaknya Visual Studio 2017 15.5 dan yang lebih baru mendukung pembuatan kelas proksi klien .NET Core . Ada juga daftar fitur yang didukung .
jamiebarrow

5
Singkatnya: CoreWCF
Ognyan Dimitrov

Jawaban:


35

WCF tidak didukung dalam .NET Core karena ini adalah teknologi khusus Windows dan .NET Core seharusnya lintas platform.

Jika Anda menerapkan komunikasi antar proses, pertimbangkan untuk mencoba proyek IpcServiceFramework .

Ini memungkinkan pembuatan layanan dalam gaya WCF seperti ini:

  1. Buat kontrak layanan

    public interface IComputingService
    {
        float AddFloat(float x, float y);
    }
    
  2. Terapkan layanan

    class ComputingService : IComputingService
    {
        public float AddFloat(float x, float y)
        {
            return x + y;
        }
    }
    
  3. Host layanan di aplikasi 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. Panggil layanan dari proses klien

    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
Bagus! Mungkin memperbarui layak untuk mengambil keuntungan dari system.io.pipelines inti Net blogs.msdn.microsoft.com/dotnet/2018/07/09/...
Sigex

Maaf, apakah saya melewatkan sesuatu yang penting di sini? Bukankah pipa seharusnya hanya untuk komunikasi host yang sama?
pengguna1034912

2
Ya, apa yang Anda lewatkan adalah bahwa ini secara singkat menunjukkan bahwa IpcServiceFramework, seperti WCF, memungkinkan Anda untuk beralih secara mulus di antara teknologi perpesanan yang berbeda.
Chris F Carroll

4
WCF mungkin dianggap windows spesifik di beberapa protokol yang abstrak, tetapi layanan SOAP tidak. Bagaimana cara membuat layanan web SOAP di .net core?
Jeremy

3
Catatan: penulis proyek ini menulis komentar berikut: "Teman-teman, karena alasan pribadi saya tidak punya waktu untuk mempertahankan proyek ini sejak beberapa bulan. Sementara .NET Core 3.0 dirilis dengan fitur gRPC." ( github.com/jacqueskang/IpcServiceFramework/issues/… ). Lihat jawaban kedua untuk gRPC.
gerard

64

Anda dapat menggunakan gRPC untuk menghosting layanan web di dalam aplikasi inti .NET.

masukkan deskripsi gambar di sini

pengantar

  1. gRPC adalah framework RPC open source berperforma tinggi yang awalnya dikembangkan oleh Google.
  2. Kerangka kerja ini didasarkan pada model klien-server panggilan prosedur jarak jauh. Aplikasi klien dapat langsung memanggil metode pada aplikasi server seolah-olah itu adalah objek lokal.

Contoh

Kode Server

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();
    }
}

Kode Klien

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();
    }
}

Kelas Bersama antara Klien dan Server

[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; }
}

Deskriptor layanan

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));
}

Serializer / Deserializer

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;
    }
}

Keluaran

Contoh keluaran klien

Output Server Sampel

Referensi

  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

Tolak ukur

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

7
Mulai Maret 2019, jawaban ini lebih relevan. Lihat github.com/grpc/grpc-dotnet (dan pembaruan ASP.NET Core di .NET Core 3.0 ).
resnyanskiy

1
Saya pikir ini adalah jawaban yang paling mendekati, tetapi tetap saja, sayangnya, itu tidak memberikan dukungan perilaku atau pembatasan apa pun.
joe

4
Ketahuilah juga bahwa saat gRPCini tidak dikompilasi terhadap rantai alat asli .net di VS 2019 (16.0.2) dan oleh karena itu tidak akan berfungsi dengan UWP.
Samuel

2
Jika Anda mencari dukungan pipa bernama, saya menulis transportasi gRPC
Cyanfish

1
Perhatikan bahwa (per 2020-04-06) grpc-dotnet tidak memiliki paket untuk ARM.
GafferMan2112

23

Tampaknya, akan ada proyek CoreWCF yang dikelola oleh .NET Foundation dengan dukungan Microsoft.

Detail selengkapnya di Menyambut Core WCF ke .NET Foundation

Awalnya hanya transport netTcp dan http yang akan diimplementasikan.


Ini jawaban yang menyesatkan. Microsoft hanya mem-porting klien wcf. Host wcf atau servicehost tidak tersedia dan mereka tidak berniat untuk melakukannya. Saya belajar ini dengan cara yang sulit. gRPC adalah cara
terbaiknya

@ user1034912 Anda salah. CoreWCF adalah server WCF ringan yang di-porting ke inti NET. Ini memiliki batasan, tetapi untuk beberapa kasus ini adalah pilihan yang baik.
Akses Ditolak

Ya, hanya jika Anda adalah Klien yang Mengkonsumsi, tidak ada implementasi
servicehost

@ user1034912 Tidak, sisi server tersedia. github.com/CoreWCF/CoreWCF/blob/master/src/Samples/…
Akses Ditolak


9

WCF melakukan banyak hal; ini adalah cara mudah untuk panggilan prosedur jarak jauh antara dua aplikasi (proses) pada satu mesin, menggunakan pipa bernama; itu bisa menjadi saluran komunikasi klien-server internal volume tinggi antara komponen NET., menggunakan serialisasi biner melalui TCPIP; atau dapat menyediakan API lintas teknologi standar, misalnya melalui SOAP. Ia bahkan memiliki dukungan untuk hal-hal seperti perpesanan asinkron, melalui MSMQ.

Untuk .NET Core, ada penggantian yang berbeda berdasarkan tujuannya.

Untuk API lintas platform, Anda akan mengganti ini dengan layanan REST menggunakan ASP.NET.

Untuk koneksi antar-proses, atau koneksi klien-server, gRPC adalah pilihan yang bagus, dengan jawaban yang sangat bagus yang diberikan oleh @Gopi.

Jadi jawaban untuk "Apa yang menggantikan WCF" tergantung pada apa Anda menggunakannya.



4

Jadi dari penelitian saya, solusi terbaik tidak memiliki kelas proxy yang dibuat secara otomatis. Solusi terbaik ini adalah membuat layanan RESTful dan menserialisasi isi respons ke dalam objek model. Dimana model tersebut merupakan objek model yang biasa terdapat pada pola desain MVC.

Terima kasih atas tanggapan Anda



Ya, kelas proxy yang dibuat secara otomatis yang saya inginkan. Saya menggunakan layanan
RESTful

Repo ini hanya untuk perpustakaan klien
orellabac

Istirahat tidak mendukung komunikasi dupleks
pengguna1034912

1

Anda juga dapat menghosting sendiri ASP.NET Core Web API.

<!-- 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}!";
    }
}

Api web inti asp tidak mendukung komunikasi dupleks pada satu port seperti yang dilakukan wcf.
pengguna1034912

0

Ada port .NET Core tersedia: https://github.com/dotnet/wcf Ini masih dalam pratinjau, tetapi mereka secara aktif mengembangkannya.


14
Saya percaya port ini untuk komunikasi dari Core ke WCF tetapi tidak untuk menulis WCF di Core.
hal9000

7
Repositori github yang ditautkan dengan jelas mengatakan: "Repo ini berisi pustaka WCF berorientasi klien yang memungkinkan aplikasi yang dibangun pada .NET Core untuk berkomunikasi dengan layanan WCF."
Bahaa

0

Karena saat ini semua selfhost WCFCore Tersedia tidak mudah untuk diinstal dan digunakan.
Yang terbaik untuk HostedService, itu akan menjadi alternatif seperti yang ditunjukkan gRPC di jawaban sebelumnya dan perhatikan bahwa dalam 1 tahun dapat mengubah banyak hal pasti WCF didukung di Core hanya sebagai klien yang berfungsi dengan baik.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.