0

I have a Windows 10 UWP application that uses WCF to make calls to our pre-existing service. The service was added to my project by adding it as a service reference, which then auto generated most of the code and the WCF client. Both the client and the service are running internally only. The service is running on an IIS server and has a self signed certificate. Because of that, we typically get a certificate error when we access or browse the service. That is fine and expected and frankly, we simply want to ignore it since we are internal only.

That said, in past applications (all written in .Net as well but with the full framework) we simply use the following code to setup the client.

    public PacTracMobileServerClient GetClient()
    {
        try
        {
            AppConfig config = new AppConfig();
            string url = config.GetODSServerAddress;

            CustomBinding binding = new CustomBinding();
            //TODO Make these timeouts configurable as well
            binding.SendTimeout = TimeSpan.FromMinutes(10);
            binding.ReceiveTimeout = TimeSpan.FromMinutes(10);

            TextMessageEncodingBindingElement tme = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
            binding.Elements.Add(tme);

            if (url.StartsWith("https", StringComparison.CurrentCultureIgnoreCase))
            {
                //HTTPS binding
                HttpsTransportBindingElement https = new HttpsTransportBindingElement();
                https.MaxReceivedMessageSize = int.MaxValue;
                https.MaxBufferSize = int.MaxValue;
                https.RequireClientCertificate = false;
                binding.Elements.Add(https);

                //Trust all certificates
                ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };
            }
            else
            {
                //HTTP binding
                HttpTransportBindingElement http = new HttpTransportBindingElement();
                http.MaxReceivedMessageSize = int.MaxValue;
                http.MaxBufferSize = int.MaxValue;
                binding.Elements.Add(http);
            }

            var ODSUri = new System.Uri(url);
            var endPoint = new EndpointAddress(ODSUri);

            var client = new PacTracMobileServerClient(binding, endPoint);

            return client;
        }
        catch (Exception ex)
        {

            return null;
        }
    }

The key to the above is the line:

 ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };

I have confirmed that with our other existing, non Windows 10 UWP applications, that if I comment out that line, I get similar errors. If I leave it in, I can access the service just fine, without errors.

Therefore, I need something similar for Windows 10 UWP. However, the ServicePointManager namespace is not available in UWP. I have seen things like creating http filters which are then passed into an httpClient to ignore certificates but since I am using the generated WCF client, I don't have an httpClient.

I have been researching this alot but because we are Windows 10 UWP AND using WCF generated code, I can't seem to find a whole lot for this specific issue.

The one thing I did find that seemed promising and tried, did not work and that is:

    public PacTracMobileServerClient GetClient()
    {
        try
        {
            AppConfig config = new AppConfig();
            string url = config.GetODSServerAddress;

            CustomBinding binding = new CustomBinding();
            //TODO Make these timeouts configurable as well
            binding.SendTimeout = TimeSpan.FromMinutes(10);
            binding.ReceiveTimeout = TimeSpan.FromMinutes(10);

            TextMessageEncodingBindingElement tme = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
            binding.Elements.Add(tme);

            if (url.StartsWith("https", StringComparison.CurrentCultureIgnoreCase))
            {
                //HTTPS binding
                HttpsTransportBindingElement https = new HttpsTransportBindingElement();
                https.MaxReceivedMessageSize = int.MaxValue;
                https.MaxBufferSize = int.MaxValue;
                https.RequireClientCertificate = false;
                binding.Elements.Add(https);

                //Trust all certificates
                //ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };
            }
            else
            {
                //HTTP binding
                HttpTransportBindingElement http = new HttpTransportBindingElement();
                http.MaxReceivedMessageSize = int.MaxValue;
                http.MaxBufferSize = int.MaxValue;
                binding.Elements.Add(http);
            }

            var ODSUri = new System.Uri(url);
            var endPoint = new EndpointAddress(ODSUri);

            var client = new PacTracMobileServerClient(binding, endPoint);
            client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

            return client;
        }
        catch (Exception ex)
        {

            return null;
        }
    }

Particularly where I do this:

                 client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

Note, the method above, GetClient, works fine in both cases and does return me a client. However, when I then actually try to call a WCF method against that client, I get an exception:

net_http_client_execution_error

UPDATE: I am trying to think outside the box here to find a solution to this. It seems I have found a hole that there is no fix for given the combination of UWP (.net core), WCF and SSL Client certificate. This has now cost me days, I spent all day researching today and thought I found something, however it still did not work. This is what I did, in the generated service reference code, I found the class that creates the client. I saw that it inherits from System.ServiceModel.ClientBase. So, I created this class:

public class MyCertificateValidator : X509CertificateValidator
{
    public MyCertificateValidator()
    {

    }

    public override void Validate(X509Certificate2 certificate)
    {

    }
}

I read that if the validate method returns, it is assumed that the certificate was validated. So, I left this method blank so that it would return. I then did this where my client is created

        this.ChannelFactory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom;
        this.ChannelFactory.Credentials.ServiceCertificate.Authentication.CustomCertificateValidator = new MyCertificateValidator();

This seems like it should work but it doesn't. Any ideas with this?

I also looked into creating a wrapper class library in .Net classic and the class library itself works fine, because by having the full .Net framework, I can do this again:

ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };

However, when I build the .dll, I cannot reference it from my UWP application. When I try to add the reference, it says that referencing a .net framework library in a .net core app is not allowed.

Please help!!!

Thanks!

Michael Bedford
  • 1,742
  • 20
  • 48
  • Have you checked FangPeng's workaround in this thread [Windows 10 Universal App - Ignore SSL Certificate Valdiation](http://stackoverflow.com/questions/32988839/windows-10-universal-app-ignore-ssl-certificate-valdiation)? As far as I know,other than only add wcf reference to your project, you also could call wcf service by HttpClient. – Xie Steven Dec 15 '16 at 08:57
  • Yes, I did see that article and the last paragraph describes my issue exactly as service point manager is not available. However, both links offer a solution to use a httpbaseprotocolfilter and they dont specifically talk about using this with a wcf client. As far as I can tell, I cannot apply the filter to the wcf client but rather, to an httpclient. Since I am using the client generated for me by the service reference, I dont have direct access to httpclient in order to apply the filter. – Michael Bedford Dec 15 '16 at 09:33
  • In addition, I hope i am missing something and there is a way to simply apply the filter to the generated wcf client because that is really all I need. I would not like it if I had to write my own client so I can use httpclient. Seems like alot of extra work and I honestly dont even know how to do it. – Michael Bedford Dec 15 '16 at 09:35
  • I’m afraid there’re no other ways to get it. Although, you might need to do a lot of extra work, but better than your app cannot work :) If you want to know how to use HttpClient to call wcf, [this article](https://long2know.com/2016/07/consuming-a-soap-service-using-httpclient/) would be helpful to you. – Xie Steven Dec 19 '16 at 08:22

0 Answers0