如何在 .Net Core 项目中使用 WcfCoreMtomEncoder?



我想在我的.Net Core项目中使用这个WcfCoreMtomEncoder库,但我不确定如何在语法上使用它。

我在下面有这段代码,但不能使用消息编码,因为我在一个 .Net Core 项目中(没有 mtom 支持(:

var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport)
{ 
// MessageEncoding = WSMessageEncoding.Mtom, not supported in .Net Core
TransferMode = TransferMode.Streamed
};
EndpointAddress endpoint = new EndpointAddress(url);
var channelFactory = new ChannelFactory<T>(binding, endpoint);
var webService = channelFactory.CreateChannel();
user.UserName = await webService.EncryptValueAsync(userName);
user.Password = await webService.EncryptValueAsync(password);
var documentAddResult = webService.DocumentAdd(document);
channelFactory.Close();

从我读到的内容来看,我可以用下面的这个库代码替换它,我从编码器库的文档中看到用法如下所示:

var encoding = new MtomMessageEncoderBindingElement(new TextMessageEncodingBindingElement());
var transport = new HttpTransportBindingElement();
var customBinding = new CustomBinding(encoding, transport);
var client = new MtomEnabledServiceClient(customBinding);

但我不确定这里是什么? 如何使用它来执行我正在尝试实现的文档上传?图书馆是这样做还是我误解了它的作用?

如果有人能为我提供一个如何使用这个库来执行文档上传的示例,将不胜感激。

按以下步骤操作:

  1. 使用 WCF 生成服务客户端,这将产生命名空间和分部类,例如DocumentWebServiceClient
  2. 在同一项目和命名空间中,创建一个文件来扩展分部类并实现用于终结点配置任务的ConfigureEndpoint方法:
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using WcfCoreMtomEncoder;
public partial class DocumentWebServiceClient // DocumentWebServiceClient is generated by the WCF
{
static partial void ConfigureEndpoint(ServiceEndpoint serviceEndpoint, ClientCredentials clientCredentials)
{
var messageEncodingBindingElementType = typeof(MessageEncodingBindingElement);
var elements = serviceEndpoint.Binding.CreateBindingElements();
IEnumerable<BindingElement> elementsWithoutEncodingElement = elements.Where(item => !messageEncodingBindingElementType.IsAssignableFrom(item.GetType()));
var existingEncodingElement = (MessageEncodingBindingElement)elements.Where(item => messageEncodingBindingElementType.IsAssignableFrom(item.GetType())).First();
var newEncodingElement = new MtomMessageEncoderBindingElement(existingEncodingElement);
// Encoding is before transport, so we prepend the MTOM message encoding binding element
// https://learn.microsoft.com/en-us/dotnet/framework/wcf/extending/custom-bindings
var cb = new CustomBinding(elementsWithoutEncodingElement.Prepend(newEncodingElement));
serviceEndpoint.Binding = cb;
}
}

经过一番挣扎,我设法创建了一个可以被类库使用的 WCF 服务。但它只支持自定义绑定。请参考以下示例。
服务器端(基于 Dotnet Framework 4.7.2 的控制台应用程序(

class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("http://localhost:21011");
MtomMessageEncodingBindingElement encoding = new MtomMessageEncodingBindingElement();
var transport = new HttpTransportBindingElement();
transport.TransferMode = TransferMode.Streamed;
var binding = new CustomBinding(encoding, transport);
using (ServiceHost sh = new ServiceHost(typeof(MyService), uri))
{
sh.AddServiceEndpoint(typeof(IService), binding, "");
ServiceMetadataBehavior smb;
smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
{
smb = new ServiceMetadataBehavior()
{
HttpGetEnabled = true
};
sh.Description.Behaviors.Add(smb);
}
Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");

sh.Opened += delegate
{
Console.WriteLine("Service is ready");
};
sh.Closed += delegate
{
Console.WriteLine("Service is clsoed");
};
sh.Open();
Console.ReadLine();
//pause
sh.Close();
Console.ReadLine();
}
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
string Test();
}
public class MyService : IService
{
public string Test()
{
return DateTime.Now.ToLongTimeString();
}
}

客户端(具有 nuget 包WcfCoreMtomEncoder基于核心的控制台应用程序,使用 ChannelFactory 调用服务(。

class Program
{
static void Main(string[] args)
{
var encoding = new MtomMessageEncoderBindingElement(new TextMessageEncodingBindingElement());
var transport = new HttpTransportBindingElement();
transport.TransferMode = TransferMode.Streamed;
var binding = new CustomBinding(encoding, transport);
EndpointAddress endpoint = new EndpointAddress("http://vabqia969vm:21011");
ChannelFactory<IService> channelFactory = new ChannelFactory<IService>(binding, endpoint);
var webService = channelFactory.CreateChannel();
Console.WriteLine(webService.Test());
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
string Test();
}

我们还要注意的一件事是,如果服务器使用传输安全模式来保护通信,我们应该手动将证书绑定到服务器端的特定端口。

Netsh http add sslcert ipport=0.0.0.0 certhash=0102030405060708090A0B0C0D0E0F1011121314 appid={00112233-4455-6677-8899-AABBCCDDEEFF}

在上面的例子中,我将一个具有命名vabqia969vm主题(DNS(的证书绑定到机器(主机名为vabqia969vm(。以下是一些官方链接。
https://learn.microsoft.com/en-us/windows/win32/http/add-sslcert
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-a-port-with-an-ssl-certificate
在客户端,在调用服务之前,我们应该建立信任关系,以便在客户端和服务器端之间进行通信。因此,我在客户端 LocalCA(证书存储中的受信任根证书颁发机构(上安装服务器证书。或者,我们可以手动添加证书验证过程。

ChannelFactory<IService> channelFactory = new ChannelFactory<IService>(binding, endpoint);
channelFactory.Credentials.ServiceCertificate.SslCertificateAuthentication = new System.ServiceModel.Security.X509ServiceCertificateAuthentication()
{
CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None,
RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
};

如果有什么我可以帮忙的,请随时告诉我。
更新。
我已经更新了上面的示例,该示例可在HTTP协议上正常工作。

你的.NET Core客户端代码应该是这样的

var encoding = new MtomMessageEncoderBindingElement(new TextMessageEncodingBindingElement());
var transport = new HttpTransportBindingElement();
var customBinding = new CustomBinding(encoding, transport);

EndpointAddress endpoint = new EndpointAddress(url);
var channelFactory = new ChannelFactory<T>(customBinding, endpoint);
var webService = channelFactory.CreateChannel();
user.UserName = await webService.EncryptValueAsync(userName);
user.Password = await webService.EncryptValueAsync(password);
var documentAddResult = webService.DocumentAdd(document);
channelFactory.Close();

扩展@divyang4481的答案。对于那些仍在为此苦苦挣扎的人,根据您与之交互的服务,您可能需要将编码更改为如下所示的内容:

var encoding = new MtomMessageEncoderBindingElement(new TextMessageEncodingBindingElement
{
MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None)
});
var transport = new HttpsTransportBindingElement();
var customBinding = new CustomBinding(encoding, transport);

我调用的Web服务抛出了一个错误,即必须使用默认的TextMessageEncodingBindingElement理解标头,因此,我必须将AddressVersion设置为none来解决问题。

相关内容

  • 没有找到相关文章

最新更新