On a recent project, we had a requirement to use a SharePoint Designer workflow to call an external web service. Instead of writing my own custom Activity, I did a search to see what was out there and found the iLove SharePoint Designer Actions. One of the actions he has in there is one that can call a SOAP 1.1 or 1.2 web service, which is exactly what I needed. Although it was written for SharePoint 2007, I pulled it into SharePoint 2010 and tested it out and found it to work just fine.
The end point for our test web service was an http address. The end point for production was https. As soon as we switched to the production end point, we began getting the error:
System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
—> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
That’s is the error we saw in the ULS logs. The nice error we saw in the workflow history was something useless like “An exception occurred”.
The error boils down to the code not trusting the secure certificate. I tried a couple non-code solutions first, one modifying the web.config:
1: <servicePointManager checkCertificateName="false" checkCertificateRevocationList="false"/>
And another importing the security certificate on the server. Neither option worked for me, although some postings I found on the Internet suggested one or the other worked for some folks.
So after exhausting the non-code solutions, I dove into the code of the iLove SharePoint Actions to add some code to tell it to ignore the certificate check. Some searching pointed me to here and here. So I pulled down the iLove SharePoint source from codeplex, opened it up in VS2010 and upgraded it. I had to change the Microsoft.SharePoint.dll references since I was using SharePoint 2010, and there were some build commands that needed to be updated as well. Once those were done, I added the line:
1: ServicePointManager.ServerCertificateValidationCallback = (obj,certificate,chain,errors) => true;
Right before the call to the web service. Once that was built and deployed, problem solved.
Looking at it from a security perspective, probably not the best solution as it opens up the possibility to call services on sites with truly invalid certificates, but being in a closed environment it was acceptable.