I am sending an XML request using C# HttpWebRequest to a Web Service authenticating through a client certificate (the certificate has been provided by a public authority and it's valid and correctly installed in the server certificate store).
Here is my code:
public void CallWebService()
{
var _url = webServiceUrl;
var _action = "soapActionToCall";
X509Certificate2 Cert = null;
try
{
//Search for the certificate in the store
X509Store Store = new X509Store(StoreName.Root);
Store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection Coll = Store.Certificates.Find(X509FindType.FindBySubjectName, "certifcateCommonName", false);
if (Coll != null && Coll.Count > 0)
{
Cert = Coll[0];
}
else
throw new Exception("Certificate non found!");
//Method to create the soap XML envelope
XmlDocument soapEnvelopeXml = CreateSoapEnvelope(typeOfService);
HttpWebRequest webRequest = CreateWebRequest(_url, _action, soapEnvelopeXml.InnerText.Length);
webRequest.ClientCertificates.Add(Cert);
InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);
// begin async call to web request.
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
// suspend this thread until call is complete. You might want to
// do something usefull here like update your UI.
asyncResult.AsyncWaitHandle.WaitOne();
// get the response from the completed web request.
string soapResult;
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
{
using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
{
soapResult = rd.ReadToEnd();
}
//Display the XML result
txtResponse.Text = soapResult;
}
}
catch (WebException webEx)
{
WebResponse errResp = webEx.Response;
string text = "";
XmlDocument xmlRsp = null;
string error = "";
if (errResp != null)
{
using (Stream respStream = errResp.GetResponseStream())
{
StreamReader reader = new StreamReader(respStream);
text = reader.ReadToEnd();
}
xmlRsp = new XmlDocument();
xmlRsp.LoadXml(text);
if (xmlRsp.GetElementsByTagName("soapenv:Fault").Count > 0)
error = xmlRsp.SelectSingleNode("//error").InnerText;
if (error.Length > 0)
throw new Exception(error);
else
throw webEx;
}
else
throw webEx;
}
}
private HttpWebRequest CreateWebRequest(string url, string action, int contentLength)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Headers.Add("SOAPAction", action);
webRequest.Host = "host";
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.ContentLength = contentLength;
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
ServicePointManager.Expect100Continue = true;
// { Ssl3 = 48, Tls = 192, Tls11 = 768, Tls12 = 3072, } }.
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
// allows for validation of SSL conversations
ServicePointManager.ServerCertificateValidationCallback = delegate(
Object obj, X509Certificate certificate, X509Chain chain,
SslPolicyErrors errors)
{
return (true);
};
return webRequest;
}
private XmlDocument CreateSoapEnvelope()
{
XmlDocument soapEnvelop = new XmlDocument();
soapEnvelop.Load("XmlFileToSend.xml");
return soapEnvelop;
}
private void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
{
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
}
I am always retrieving the error "The request was aborted: Could not create SSL/TLS secure channel." when the code enter the method InsertSoapEnvelopeIntoWebRequest at the webRequest.GetRequestStream() line. Do someone have idea to help me?