Was ersetzt WCF in .Net Core?


95

Ich bin es gewohnt, eine .Net Framework-Konsolenanwendung zu erstellen und eine Add(int x, int y)Funktion über einen WCF-Dienst von Grund auf mit Class Library (.Net Framework) verfügbar zu machen. Ich benutze dann die Konsolenanwendung, um diese Funktion innerhalb des Servers als Proxy aufzurufen.

Wenn ich jedoch die Konsolen-App (.Net Core) und eine Klassenbibliothek (.Net Core) verwende, ist das System.ServiceModel nicht verfügbar. Ich habe ein bisschen gegoogelt, aber ich habe nicht herausgefunden, was WCF in diesem Fall "ersetzt".

Wie mache ich eine Add(int x, int y)Funktion in einer Klassenbibliothek für eine Konsolenanwendung in .Net Core verfügbar? Ich sehe System.ServiceModel.Web, und da dies versucht, plattformübergreifend zu sein, muss ich einen RESTful-Service erstellen?


do I have to create a RESTful service?- AFAIK ja (oder verwenden Sie eine Drittanbieterlösung, die ich für .NET Core nicht kennen würde)
Christoph Fink

3
WCF wird wahrscheinlich nicht auf .NET Core portiert, da der größte Teil der Codebasis von internen Windows-Bibliotheken abhängt. Können Sie ASP.NET Core verwenden? Dort haben Sie einen HTTP-Server, der leicht plattformübergreifend ist
Camilo Terevinto

2
Die clientseitige WCF-Seite wird bereits unterstützt (ich weiß nicht, wie viel), die serverseitige ist eine heiß diskutierte und abgestimmte Feature-Anfrage.
Henk Holterman

Es scheint, dass Visual Studio 2017 15.5 und höher das Generieren von .NET Core-Client-Proxyklassen unterstützt . Es gibt auch eine Liste der unterstützten Funktionen .
Jamie Barrow

Antworten:


34

WCF wird in .NET Core nicht unterstützt, da es sich um eine Windows-spezifische Technologie handelt und .NET Core plattformübergreifend sein soll.

Wenn Sie prozessübergreifende Kommunikation implementieren, versuchen Sie es mit dem IpcServiceFramework- Projekt.

Es ermöglicht das Erstellen von Diensten im WCF-Stil wie folgt:

  1. Servicevertrag anlegen

    public interface IComputingService
    {
        float AddFloat(float x, float y);
    }
    
  2. Implementieren Sie den Service

    class ComputingService : IComputingService
    {
        public float AddFloat(float x, float y)
        {
            return x + y;
        }
    }
    
  3. Hosten Sie den Dienst in der Konsolenanwendung

    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. Rufen Sie den Service vom Client-Prozess aus auf

    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
Nett! Könnte eine Aktualisierung wert sein, um die Vorteile des .Net-Kernsystems system.io.pipelines blogs.msdn.microsoft.com/dotnet/2018/07/09/… zu nutzen
Sigex

Entschuldigung, fehlt mir hier etwas Wichtiges? Sollen Pipes nicht nur für die gleiche Host-Kommunikation verwendet werden?
user1034912

2
Ja, was Sie vermissen, ist, dass dies kurz zeigt, dass IpcServiceFramework wie WCF es Ihnen ermöglicht, nahtlos zwischen verschiedenen Messaging-Technologien zu wechseln.
Chris F Carroll

4
WCF kann in einigen der abstrahierten Protokolle als Windows-spezifisch angesehen werden, SOAP-Dienste jedoch nicht. Wie würde man einen SOAP-Webdienst im .net-Kern erstellen?
Jeremy

3
Hinweis: Der Autor dieses Projekts schrieb den folgenden Kommentar: "Leute, aus persönlichen Gründen habe ich seit einigen Monaten keine Zeit mehr, dieses Projekt zu warten. In der Zwischenzeit wird .NET Core 3.0 mit der gRPC-Funktion veröffentlicht." ( github.com/jacqueskang/IpcServiceFramework/issues/… ). Siehe die zweite Antwort für gRPC.
Gerard

63

Sie können gRPC zum Hosten von Webdiensten in der .NET-Kernanwendung verwenden.

Geben Sie hier die Bildbeschreibung ein

Einführung

  1. gRPC ist ein leistungsstarkes Open-Source-RPC-Framework, das ursprünglich von Google entwickelt wurde.
  2. Das Framework basiert auf einem Client-Server-Modell von Remoteprozeduraufrufen. Eine Clientanwendung kann Methoden in einer Serveranwendung direkt aufrufen, als wäre es ein lokales Objekt.

Beispiel

Servercode

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

Kundencode

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

Gemeinsame Klassen zwischen Client und 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; }
}

Service-Deskriptoren

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

Ausgabe

Beispiel für eine Client-Ausgabe

Beispielserverausgabe

Verweise

  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

Benchmarks

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

7
Ab März 2019 ist diese Antwort relevanter. Siehe github.com/grpc/grpc-dotnet (und ASP.NET Core-Updates in .NET Core 3.0 ).
resnyanskiy

1
Ich denke, dies ist die naheliegendste Antwort, aber leider bietet sie kein Verhalten oder keine Drosselungsunterstützung.
Joe

4
gRPCBeachten Sie auch, dass derzeit keine Kompilierung mit der nativen .net-Toolkette in VS 2019 (16.0.2) möglich ist und daher nicht mit UWP funktioniert.
Samuel

2
Wenn Sie nach
Named

1
Beachten Sie, dass grpc-dotnet (Stand 2020-04-06) keine Pakete für ARM enthält.
GafferMan2112

23

Es scheint, dass es ein CoreWCF- Projekt geben wird, das von .NET Foundation mit Microsoft-Unterstützung verwaltet wird.

Weitere Informationen finden Sie unter Begrüßung von Core WCF bei der .NET Foundation

Zunächst werden nur netTcp- und http-Transporte implementiert.


Dies ist eine irreführende Antwort. Microsoft hat nur den wcf-Client portiert. Wcf-Host oder -Servicehost ist nicht verfügbar und sie haben nicht die Absicht, dies zu tun. Ich habe das auf die harte Tour gelernt. gRPC ist der
richtige

@ user1034912 Sie sind nicht korrekt. CoreWCF ist ein leichter WCF-Server, der auf den .NET-Kern portiert ist. Es hat Einschränkungen, aber in einigen Fällen ist es eine gute Wahl.
Zugriff

Ja, nur wenn Sie ein Consuming Client sind, gibt es
Service-Host-

@ user1034912 Nein, die Serverseite ist verfügbar. github.com/CoreWCF/CoreWCF/blob/master/src/Samples/…
Zugriff


9

WCF macht viele Dinge; Es ist eine einfache Möglichkeit, Remoteprozeduraufrufe zwischen zwei Anwendungen (Prozessen) auf einem Computer mithilfe von Named Pipes durchzuführen. Es kann sich um einen internen Client-Server-Kommunikationskanal mit hohem Volumen zwischen .NET-Komponenten handeln, der eine binäre Serialisierung über TCPIP verwendet. oder es kann eine standardisierte technologieübergreifende API bereitstellen, z. B. über SOAP. Es unterstützt sogar asynchrones Messaging über MSMQ.

Für .NET Core gibt es je nach Zweck unterschiedliche Ersetzungen.

Bei einer plattformübergreifenden API würden Sie diese mithilfe von ASP.NET durch einen REST-Service ersetzen.

Für prozessübergreifende Verbindungen oder Client-Server-Verbindungen wäre gRPC gut, mit einer ausgezeichneten Antwort von @Gopi.

Die Antwort auf "Was ersetzt WCF" hängt also davon ab, wofür Sie es verwenden.



4

Aus meiner Forschung hat die beste Lösung also nicht die automatisch generierten Proxy-Klassen. Diese beste Lösung besteht darin, einen RESTful-Service zu erstellen und den Antworttext in Modellobjekte zu serialisieren. Wo die Modelle die üblichen Modellobjekte sind, die im MVC-Entwurfsmuster gefunden werden.

Vielen Dank für Ihre Antworten



Ja, es waren die automatisch generierten Proxy-Klassen, die ich wollte. Ich benutze RESTful Services / RPC für diese Funktionalität
Sigex

Dieses Repo ist nur für die Client-Bibliotheken
Orellabac

Restful unterstützt keine Duplex-Kommunikation
user1034912

1

Sie können die ASP.NET Core-Web-API auch selbst hosten.

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

Die Asp Core Web-API unterstützt keine Duplex-Kommunikation an einem einzelnen Port, wie dies bei wcf der Fall ist.
user1034912

0

Es ist ein .NET Core-Port verfügbar: https://github.com/dotnet/wcf Er befindet sich noch in der Vorschau, wird jedoch aktiv weiterentwickelt.


14
Ich glaube, dieser Port dient zur Kommunikation von Core zu WCF, aber nicht zum Schreiben von WCF in Core.
hal9000

7
Das verknüpfte Github-Repository sagt deutlich: "Dieses Repo enthält die clientorientierten WCF-Bibliotheken, mit denen auf .NET Core basierende Anwendungen mit WCF-Diensten kommunizieren können."
Bahaa

0

Wie heute sind alle verfügbaren WCFCore-Selfhosts nicht so einfach zu installieren und zu verwenden.
Das Beste für HostedService sind die Alternativen, wie gRPC in der vorherigen Antwort gezeigt hat. Beachten Sie, dass sich in einem Jahr viele Dinge ändern können, um sicherzustellen, dass WCF in Core nur als Client unterstützt wird, der einwandfrei funktioniert.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.