And*_*vva 19 c# wcf soap xml-serialization soap-client
我当前的实现是利用ClientBase类为第三方API的WCF调用创建一个通道.此第三方API需要对X509Certificate2证书以及ClientCredentials进行身份验证.
public class HeaderAdder : ContextBoundObject, IClientMessageInspector
{
public bool RequestFailedDueToAuthentication;
public string UserName { get; set; }
public string Password { get; set; }
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var property = new UserNameHeader
{
Password = Password,
UserName = UserName
};
request.Headers.Add(MessageHeader.CreateHeader("UserNameHeader", "test", property));
return null;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
RequestFailedDueToAuthentication = reply.ToString().Contains("ErrorCode>-4<");
}
}
public class CustomEndpointBehavior : IEndpointBehavior
{
private readonly HeaderAdder _headerAdder;
public CustomEndpointBehavior(HeaderAdder headerAdder)
{
_headerAdder = headerAdder;
}
public void Validate(ServiceEndpoint endpoint)
{
//throw new NotImplementedException();
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
//throw new NotImplementedException();
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
//throw new NotImplementedException();
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
var credentials = endpoint.Behaviors.Find<ClientCredentials>();
if (!string.IsNullOrEmpty(credentials.UserName.Password))
{
_headerAdder.UserName = credentials.UserName.UserName;
_headerAdder.Password = credentials.UserName.Password;
clientRuntime.ClientMessageInspectors.Add(_headerAdder);
}
}
}
Run Code Online (Sandbox Code Playgroud)
客户端实例化和请求可以在这里看到:
var client = new TestClient()
{
ClientCredentials =
{
UserName =
{
UserName = "testing",
Password = "testing"
},
UseIdentityConfiguration = true
}
};
client.ClientCredentials?.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindByIssuerName,
"Testing");
client.ChannelFactory.Endpoint.EndpointBehaviors.Add(
new CustomEndpointBehavior(new HeaderAdder()));
var request = new Request();
client.Get(request);
Run Code Online (Sandbox Code Playgroud)
不幸的是,为WCF调用创建Channel的过程需要9秒以上才能完成.使用ReSharper的doTrace探查器,我能够看到代码在以下方法上被阻止:System.ServiceModel.Description.XmlSerializer.OperationBehavior + Reflecto.EnsureMessageInfos
可以在下面看到在System.ServiceModel中进行的调用的完整堆栈跟踪.
System.ServiceModel.ClientBase`1.get_Channel
System.ServiceModel.ClientBase`1.CreateChannelInternal
System.ServiceModel.ClientBase`1.CreateChannel
System.ServiceModel.ChannelFactory`1.CreateChannel
System.ServiceModel.ChannelFactory`1.CreateChannel(EndpointAddress, Uri)
System.ServiceModel.ChannelFactory.EnsureOpened
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan)
System.ServiceModel.ChannelFactory.OnOpening
System.ServiceModel.ChannelFactory.CreateFactory
System.ServiceModel.Channels.ServiceChannelFactory.BuildChannelFactory(ServiceEndpoint, Boolean)
System.ServiceModel.Description.DispatcherBuilder.BuildProxyBehavior(ServiceEndpoint, out BindingParameterCollection)
System.ServiceModel.Description.DispatcherBuilder.ApplyClientBehavior(ServiceEndpoint, ClientRuntime)
System.ServiceModel.Description.DispatcherBuilder.BindOperations(ContractDescription, ClientRuntime, DispatchRuntime)
System.ServiceModel.Description.XmlSerializerOperationBehavior.ApplyClientBehavior(OperationDescription, ClientOperation)
System.ServiceModel.Description.XmlSerializerOperationBehavior.CreateFormatter
System.ServiceModel.Description.XmlSerializerOperationBehavior+Reflector.EnsureMessageInfos
Run Code Online (Sandbox Code Playgroud)
我已经尝试使用sgen.exe来创建XML序列化程序集,希望它能提高序列化程序的性能.不幸的是,它没有任何效果.
我还在网上找到了几种建议缓存渠道或渠道工厂的方法,例如http://www.itprotoday.com/microsoft-visual-studio/wcf-proxies-cache-or-not-cache.但是,这些方法不适用于此实现,因为Channel Factory具有与之关联的客户端凭据.这将需要为每个客户端缓存一个Channel Factory或Channel,这是不现实的.
有没有人知道一种方法可以防止ChannelFactory在创建时反映出Request和Response对象?任何人都可以在这个问题上提供的任何帮助将非常感谢.
| 归档时间: |
|
| 查看次数: |
526 次 |
| 最近记录: |