我为当前的雇主开发了一个客户端/服务器应用程序,其中一个要求是客户端部分作为DLL分发。由于DLL不“执行”dllName.dll.config文件,我需要将配置移动到代码中。我尽我所能做到了这一点,但我现在得到了这个例外;
X.509证书CN = ComputerName链建设失败 使用的证书具有不能的信任链 被核实。替换证书或更改certificateValidationMode。 发生了内部证书链错误。
我已经谷歌搜索,并以其他方式搜索了解决方案,但到目前为止,我找不到任何有足够清楚解释我所看到的各种近似但不是真正解决方案的内容。
无论如何,My LocalStore中有一个证书,但它实际上只供服务器使用(目前在同一个XP Pro盒子上测试客户端和服务器),至少就我所理解的事情而言。 (对于WCF来说还是新手)(注意下面的客户端配置文件如何获取或以其他方式向客户端指出上述证书。
客户端的app.config看起来如下所示,并且通过我们的测试EXE工作得非常好,它包含了这个配置文件的部分。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="MyTcpBinding_IFileXferService"
receiveTimeout="02:00:00"
sendTimeout="02:00:00"
transferMode="Streamed"
maxBufferSize="65536"
maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="65536" />
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ClientConfigBehavior">
<dataContractSerializer maxItemsInObjectGraph="6553600" />
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="None" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint name="ClientConfig"
binding="netTcpBinding"
bindingConfiguration="MyTcpBinding_IFileXferService"
behaviorConfiguration="ClientConfigBehavior"
contract="ServiceRefs.IFileXferService" />
</client>
</system.serviceModel>
</configuration>
但是现在我已经将配置信息移动到代码中(这样可以在没有.config文件的情况下分发DLL),我再次获得上面提到的异常。 (顺便说一句,如果我们发现给定的设置需要变化,我可以将它添加到我们自己的xml配置文件中。)
用于替换上述配置的代码如下所示:
...
netTcpBinding = new NetTcpBinding();
endpointAddr = new EndpointAddress(HostURI);
updateMaxItemsBehavior(); // method below this snippet
TimeSpan tsTwoHours = new TimeSpan(2,0,0);
netTcpBinding.ReceiveTimeout = tsTwoHours;
netTcpBinding.SendTimeout = tsTwoHours;
netTcpBinding.TransferMode = TransferMode.Streamed;
netTcpBinding.MaxBufferSize = 65536;
netTcpBinding.MaxReceivedMessageSize = 2147483647;
netTcpBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
netTcpBinding.ReaderQuotas.MaxArrayLength = 2147483647;
netTcpBinding.ReaderQuotas.MaxBytesPerRead = 65536;
// double the 64k default
netTcpBinding.MaxBufferPoolSize = 131072;
netTcpBinding.Security.Mode = SecurityMode.Transport;
netTcpBinding.Security.Transport.ClientCredentialType =
TcpClientCredentialType.None;
// now to instantiate the service proxy client
svcClient = new FileXferServiceClient(netTcpBinding, endpointAddr);
我已尝试使用这些下一位的各种组合,但不能 绕过dang例外。
// Set the certificate for the client.
X509Certificate2 cert = new X509Certificate2();
svcClient.ClientCredentials.ClientCertificate.Certificate = cert;
//svcClient.ClientCredentials.ClientCertificate.SetCertificate(
// StoreLocation.LocalMachine,
// StoreName.My,
// X509FindType.FindByThumbprint,
// "ThumbprintThumbprintThumbprintThumbprint");
// here's this
//
private void updateMaxItemsBehavior()
{
svcEndpoint = new ServiceEndpoint(
new ContractDescription("IFileXferService"));
foreach (OperationDescription operation in
svcEndpoint.Contract.Operations)
{
operation.Behaviors
.Find<DataContractSerializerOperationBehavior>()
.MaxItemsInObjectGraph = 6553600;
}
}
总之,我们的测试Winforms应用程序(以及我们的WCF应用程序的客户端)可以正常使用wfappname.exe.config文件中的配置设置,但现在我已经尝试将此全部移动到代码中,它显然要求证书。我想我真正希望的是“我如何在代码中复制上面的app.config,以便我的WCF客户端不需要app.config。”
任何人都可以帮我吗? (我会成为你最好的朋友!); )
谢谢, 斯科特
答案 0 :(得分:3)
我觉得你是男人。
我不喜欢在将WCF服务部署到IIS时将.config内容嵌入到web.config中的想法,或者在以其他方式托管时转换.config并嵌入代码中。
我解决这个问题的方法是使用一个自定义服务主机来覆盖默认的ApplyConfiguration()逻辑。它允许在服务端,WCF DLL查看dllname.dll.config(或任何地方,真的)进行配置。
是all explained here。该信息也在this answer on Stackoverflow中重复。
您正在使用WCF客户端,因此您需要覆盖ApplyConfiguration() method in a custom ChannelFactory。这被描述为here。在同一篇论坛帖子中,描述了一种替代技术,您可以覆盖CreateDescription()并指定备用.config文件路径。这些方法非常相似;要么应该在WCF客户端工作。
您也可以考虑将.config嵌入到嵌入到.dll中的资源中。这样,您仍然可以使用单文件分发(dll),但您可以使用xml配置语法来指定所有内容。在构建时,将.config文件嵌入到DLL中。在自定义ApplyConfiguration()内的运行时,您必须调用 Assembly.GetManifestResourceStream();,传递字符串“dllname.dll.config”以获取包含配置信息的只读流。
如果您希望允许用户覆盖嵌入式配置,那么您可以将该智能引入您自己的ApplyConfiguration()实现中。可能首先查找文件系统文件;如果它不存在,则回退到嵌入的.config文件。
这个答案并没有真正告诉你如何将配置设置转换为代码,因为我认为这是一个令人发指的想法。但也许它无论如何都能解决你的问题。