我的特殊问题是这样的:
我的代码是这样的:
try
{
// Define the metadata address, contract name, operation name,
// and parameters.
// You can choose between MEX endpoint and HTTP GET by
// changing the address and enum value.
Uri mexAddress = new Uri("http://Some3rdPartyURL.svc?wsdl");//Some 3rd party url
// For MEX endpoints use a MEX address and a
// mexMode of .MetadataExchange
MetadataExchangeClientMode mexMode = MetadataExchangeClientMode.HttpGet;
string contractName = "IService";//"";//3rd party service name
string operationName = "SendMethod";//3rd party method name
object[] args = new object[] { "", "", "0" };//3rd party required parameters
//object[] operationParameters = new object[] { /*1, 2*/args };
// Get the metadata file from the service.
MetadataExchangeClient mexClient =
new MetadataExchangeClient(mexAddress, mexMode);
mexClient.ResolveMetadataReferences = true;
MetadataSet metaSet = mexClient.GetMetadata();
// Import all contracts and endpoints
WsdlImporter importer = new WsdlImporter(metaSet);
Collection<ContractDescription> contracts =
importer.ImportAllContracts();
ServiceEndpointCollection allEndpoints = importer.ImportAllEndpoints();
// Generate type information for each contract
ServiceContractGenerator generator = new ServiceContractGenerator();
var endpointsForContracts = new Dictionary<string, IEnumerable<ServiceEndpoint>>();
foreach (ContractDescription contract in contracts)
{
generator.GenerateServiceContractType(contract);
// Keep a list of each contract's endpoints
endpointsForContracts[contract.Name] = allEndpoints.Where(
se => se.Contract.Name == contract.Name).ToList();
}
if (generator.Errors.Count != 0)
throw new Exception("There were errors during code compilation.");
// Generate a code file for the contracts
CodeGeneratorOptions options = new CodeGeneratorOptions();
options.BracingStyle = "C";
CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("C#");
// Compile the code file to an in-memory assembly
// Don't forget to add all WCF-related assemblies as references
CompilerParameters compilerParameters = new CompilerParameters(
new string[] {
"System.dll", "System.ServiceModel.dll",
"System.Runtime.Serialization.dll"});
compilerParameters.GenerateInMemory = true;
CompilerResults results = codeDomProvider.CompileAssemblyFromDom(
compilerParameters, generator.TargetCompileUnit);
if (results.Errors.Count > 0)
{
throw new Exception("There were errors during generated code compilation");
}
else
{
// Find the proxy type that was generated for the specified contract
// (identified by a class that implements
// the contract and ICommunicationbject)
Type clientProxyType = results.CompiledAssembly.GetTypes().First(
t => t.IsClass &&
t.GetInterface(contractName) != null &&
t.GetInterface(typeof(ICommunicationObject).Name) != null);
// Get the first service endpoint for the contract
ServiceEndpoint se = endpointsForContracts[contractName].First();
//se = endpointsForContracts[contractName].First();
WSHttpBinding wsBinding = this.fillWsHttpBinding();
string encodeValue = "MIIFazCCBFO****"; // here we should use the encoded certificate value generated by svcutil.exe.
X509Certificate2Collection supportingCertificates = new X509Certificate2Collection();
supportingCertificates.Import(Convert.FromBase64String(encodeValue));
X509Certificate2 primaryCertificate = supportingCertificates[0];
supportingCertificates.RemoveAt(0);
EndpointIdentity.CreateX509CertificateIdentity(primaryCertificate, supportingCertificates);
EndpointIdentity identity = EndpointIdentity.CreateX509CertificateIdentity(primaryCertificate);
var endpoint = new EndpointAddress(mexAddress, identity);
se.Binding = wsBinding;
se.Address = endpoint;
// Create an instance of the proxy
// Pass the endpoint's binding and address as parameters
// to the ctor
object instance = results.CompiledAssembly.CreateInstance(
clientProxyType.Name,
false,
System.Reflection.BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance,
null,
new object[] { se.Binding, se.Address }, CultureInfo.CurrentCulture, null);
var methodInfo = instance.GetType().GetMethod(operationName);
var methodParams = methodInfo.GetParameters();
int count = args.Count();
object[] args2 = new object[count];
int i = 0;
foreach (var service1 in methodParams)
{
args2[i] = Convert.ChangeType(args[i], Type.GetType("System." + service1.ParameterType.Name));
i += 1;
}
Object retVal = instance.GetType().GetMethod(operationName).Invoke(instance, args2);/*Getting Error that certificate not provided???*/
}
}
catch (Exception ex)
{
string error = ex.ToString();
MessageBox.Show("Error Invoking Method: " + ex.Message);
}
private WSHttpBinding fillWsHttpBinding() {
WSHttpBinding wsBinding = new WSHttpBinding();
wsBinding.CloseTimeout = new TimeSpan(0, 1, 0);
wsBinding.OpenTimeout = new TimeSpan(0, 10, 0);
wsBinding.ReceiveTimeout = new TimeSpan(0, 10, 0);
wsBinding.SendTimeout = new TimeSpan(0, 5, 30);
wsBinding.BypassProxyOnLocal = false;
wsBinding.TransactionFlow = false;
wsBinding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
wsBinding.MaxBufferPoolSize = 524288L;
wsBinding.MaxReceivedMessageSize = 10485760L;
wsBinding.MessageEncoding = WSMessageEncoding.Text;
wsBinding.TextEncoding = Encoding.UTF8;
wsBinding.UseDefaultWebProxy = true;
wsBinding.AllowCookies = false;
wsBinding.ReaderQuotas.MaxDepth = 32;
wsBinding.ReaderQuotas.MaxStringContentLength = 8192;
wsBinding.ReaderQuotas.MaxArrayLength = 10485760;
wsBinding.ReaderQuotas.MaxNameTableCharCount = 16384;
wsBinding.ReliableSession.Ordered = true;
wsBinding.ReliableSession.InactivityTimeout = TimeSpan.FromMinutes(10);
wsBinding.ReliableSession.Enabled = false;
wsBinding.Security.Mode = SecurityMode.Message;
wsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
wsBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
wsBinding.Security.Transport.Realm = "";
wsBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
wsBinding.Security.Message.NegotiateServiceCredential = true;
wsBinding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic256;
return wsBinding;
}
答案 0 :(得分:1)
在EndpointIdentity
上设置证书的位置会导致它用于验证服务的身份。您尚未使用instance.ClientCredentials.ClientCertificate.SetCertificate(...)
设置客户端的凭据。您必须从ClientBase&lt;&gt;获取ClientCredentials使用反射。请参阅http://msdn.microsoft.com/en-us/library/ms732391%28v=vs.110%29.aspx。
var credentialProperty = instance.GetType().GetProperty("ClientCredentials");
var credentials = (ClientCredentials)credentialProperty.GetValue(instance, null);
credentials.ClientCertificate.SetCertficate(...);
您还有两次拨打EndpointIdentity.CreateX509CertificateIdentity
,忽略了其中一个的输出。