Estoy acostumbrado a crear una aplicación de consola .Net Framework y exponer una Add(int x, int y)
función a través de un servicio WCF desde cero con Class Library (.Net Framework). Luego utilizo la aplicación de consola para llamar a esta función dentro del servidor.
Sin embargo, si uso la aplicación de consola (.Net Core) y una biblioteca de clases (.Net Core), System.ServiceModel no está disponible. He hecho algunas búsquedas en Google, pero no he descubierto qué "reemplaza" a WCF en este caso.
¿Cómo expongo una Add(int x, int y)
función dentro de una biblioteca de clases a una aplicación de consola dentro de .Net Core? Veo System.ServiceModel.Web, y dado que esto intenta ser multiplataforma, ¿tengo que crear un servicio RESTful?
do I have to create a RESTful service?
- AFAIK, sí (o use alguna solución de terceros que no conocería para .NET Core)Respuestas:
WCF no es compatible con .NET Core porque es una tecnología específica de Windows y se supone que .NET Core es multiplataforma.
Si está implementando la comunicación entre procesos, considere probar el proyecto IpcServiceFramework .
Permite crear servicios en estilo WCF como este:
Crear contrato de servicio
public interface IComputingService { float AddFloat(float x, float y); }
Implementar el servicio
class ComputingService : IComputingService { public float AddFloat(float x, float y) { return x + y; } }
Alojar el servicio en la aplicación de consola
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>(); } }
Invocar el servicio desde el proceso del cliente
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));
fuente
Puede utilizar gRPC para alojar servicios web dentro de la aplicación principal .NET.
Introducción
Ejemplo
Código del servidor
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(); } }
Codigo del cliente
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(); } }
Clases compartidas entre cliente y servidor
[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; } }
Descriptores de servicio
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)); }
Serializador / Deserializador
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; } }
Salida
Salida de cliente de muestra
Salida del servidor de muestra
Referencias
Benchmarks
fuente
gRPC
no se compila con la cadena de herramientas nativas .net en VS 2019 (16.0.2) y, por lo tanto, no funcionará con UWP.Parece que habrá un proyecto CoreWCF mantenido por .NET Foundation con soporte de Microsoft.
Más detalles en Bienvenido a Core WCF a .NET Foundation
Inicialmente, solo se implementarán el transporte netTcp y http.
fuente
WCF hace muchas cosas; es una manera fácil de realizar llamadas a procedimientos remotos entre dos aplicaciones (procesos) en una máquina, utilizando canalizaciones con nombre; puede ser un canal de comunicación cliente-servidor interno de alto volumen entre componentes .NET, utilizando serialización binaria sobre TCPIP; o puede proporcionar una API de tecnología cruzada estandarizada, por ejemplo, a través de SOAP. Incluso tiene soporte para cosas como mensajería asincrónica, a través de MSMQ.
Para .NET Core, existen diferentes reemplazos según el propósito.
Para API multiplataforma, lo reemplazaría con un servicio REST usando ASP.NET.
Para conexiones entre procesos, o conexión cliente-servidor, gRPC sería bueno, con una excelente respuesta dada por @Gopi.
Entonces, la respuesta a "Lo que reemplaza a WCF" depende de para qué lo esté usando.
fuente
Hay un repositorio de la comunidad https://github.com/CoreWCF/CoreWCF que implementa algunas partes de WCF. Puede usarlo para admitir algunos servicios WCF simples. Sin embargo, no todas las funciones son compatibles.
fuente
Entonces, de mi investigación, la mejor solución no tiene las clases de proxy generadas automáticamente. Esta mejor solución es crear un servicio RESTful y serializar el cuerpo de respuesta en objetos de modelo. Donde los modelos son los objetos de modelo habituales que se encuentran en el patrón de diseño MVC.
Gracias por sus respuestas
fuente
También puede autohospedar la API web 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}!"; } }
fuente
Hay un puerto .NET Core disponible: https://github.com/dotnet/wcf Todavía está en versión preliminar, pero lo están desarrollando activamente.
fuente
Como en la actualidad, todos los selfhost disponibles de WCFCore no son tan fáciles de instalar y usar.
Lo mejor para HostedService serán las alternativas como gRPC mostró en la respuesta anterior y observe que en 1 año pueden cambiar muchas cosas, seguro que WCF es compatible con Core solo como un cliente que funciona bien.
fuente