有一个旧服务是使用WCF作为服务端的,并且绑定的终结点使用了net.tcp://
现在需要写一个新的ASP .NET Core项目,需要调用到WCF服务的方法
我的做法是把.NET Framework项目的WCF客户端连接服务端的代码生成为dll,然后在ASP .NET Core项目中引用该dll,在需要使用的地方直接调用dll封装好的方法,但是实际运行中项目报错:“找不到System.ServiceModel引用”。
不知道还有没有其他方法可以调用到WCF服务的方法?
在 ASP .NET Core 项目中调用使用 net.tcp 协议的 WCF 服务,由于 .NET Core 不再支持 System.ServiceModel 命名空间,所以无法直接使用传统的 WCF 客户端代码。但你仍然有几个选择来实现调用 WCF 服务的方法:
使用 WCF Connected Services 扩展:
ASP .NET Core 提供了 WCF Connected Services 扩展,它允许你在 .NET Core 项目中连接和调用 WCF 服务。这个扩展会自动生成所需的代码,让你能够轻松地与 WCF 服务交互。请注意,该扩展可能需要你的 WCF 服务使用了基本的 HttpBinding 绑定,而不是 net.tcp 绑定。
在 Visual Studio 中打开 ASP .NET Core 项目,在“项目”菜单中选择“添加连接服务”,然后按照提示连接到 WCF 服务。如果你的 WCF 服务是基于 net.tcp 协议的,可能会提示无法连接,这种情况下你可以尝试下面的第2种方法。
使用 BasicHttpBinding 代替 net.tcp 绑定:
由于 .NET Core 不支持 net.tcp 绑定,你可以尝试将 WCF 服务的终结点改为基本的 HttpBinding 绑定,这样就可以使用 WCF Connected Services 扩展来连接和调用服务。修改 WCF 服务配置文件,将终结点绑定改为 BasicHttpBinding。
使用第三方库或手动实现:
如果以上方法无法满足需求,你可以考虑使用第三方库,如 gRPC、ServiceStack 等,它们提供了更现代化的跨平台服务通信方式。另外,你还可以尝试手动实现基于 net.tcp 协议的自定义通信,但这会比较复杂。
综上所述,最推荐的方法是使用 WCF Connected Services 扩展来连接和调用 WCF 服务。如果无法直接连接,可以尝试将 WCF 服务的绑定改为基本的 HttpBinding 绑定。如果仍然无法满足需求,可以考虑使用第三方库或手动实现。请注意,由于 .NET Core 是跨平台的,与传统的 .NET Framework 有一些不同,因此在集成旧的 WCF 服务时可能需要做一些调整和权衡。
using System;
using System.Net;
using System.Threading.Tasks;
using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
public class WcfClientHandler : SimpleChannelInboundHandler2<IByteBuffer>
{
private readonly TaskCompletionSource<string> _tcs;
public WcfClientHandler()
{
_tcs = new TaskCompletionSource<string>();
}
protected override void ChannelRead0(IChannelHandlerContext context, IByteBuffer message)
{
var response = message.ToString(Encoding.UTF8);
_tcs.SetResult(response);
}
public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
{
_tcs.SetException(exception);
}
public Task<string> SendRequest(string request)
{
// 创建连接
var group = new MultithreadEventLoopGroup();
var bootstrap = new Bootstrap();
bootstrap
.Group(group) .Channel<TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer<ISocketChannel>(channel => { var pipeline = channel.Pipeline; pipeline.AddLast(new LengthFieldBasedFrameDecoder(8192, 0, 4, 0, 4)); pipeline.AddLast(new StringDecoder(Encoding.UTF8)); pipeline.AddLast(new LengthFieldPrepender(4)); pipeline.AddLast(new StringEncoder(Encoding.UTF8)); pipeline.AddLast(this); }));
// 发送请求并等待响
try
{
var endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8000);
var channel = await bootstrap.ConnectAsync(endPoint);
// 构造请求消息
var buffer = Unpooled.Buffer();
buffer.WriteInt(request.Length);
buffer.WriteString(request, Encoding.UTF8);
// 发送请求消息
await channel.WriteAndFlushAsync(buffer);
// 等待响应消息
var response = await _tcs.Task;
// 关闭连接
await channel.CloseAsync();
return response;
}
finally
{
await group.ShutdownGracefullyAsync();
}
}
}
public class Program { public static async Task Main(string[] args) { var handler = new WcfClientHandler(); var response = await handler.SendRequest("Hello WCF service!");
后来发现原来官方提供了.NET Core版本的WCF库
我是.NET 6项目,并且需要连接的WCF服务是net.tcp协议的
在NuGet包下载以下包:
System.ServiceModel.Primitves
System.ServiceModel.NetTcp
使用方法和.NET Framework中的System.ServiceModel几乎一模一样:
// ...
NetTcpBinding tcpBinding = new NetTcpBinding();
tcpBinding.ReceiveTimeout = TimeSpan.MaxValue;
// 配置tcpBinding
...
IServiceCallback callbackInstance = new ServiceCallbackImpl();
InstanceContext instanceContext = new InstanceContext(callbackInstance);
DuplexChannelFactory<IService> duplexChancelFactory = new DuplexChannelFactory<IService>(instanceContext, tcpBinding, new EndpointAddress("net.tcp://..."));
IService service = duplexChancelFactory.CreateChannel();
// ...