Thursday, August 26, 2021

Dynamically calling WCF service over HTTP and HTTPS with Certificate and without Certificate In C#.net

Here I am trying to call the WCF Service through C#.net code for testing purpose.

My scenario is, I want to call WCF Service from BizTalk over HTTPS protocol with Certificate
so first I was written the C# code to test it as below.

Step 1: Create a console application and add the service reference and create one class as I written,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.IO;
using System.Net;
using System.Configuration;
using System.Xml.Serialization;
using System.Xml.Linq;
using System.ServiceModel;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

namespace WCFClientApp
{
    class CallWcfServiceWithCertificate
    {

        private static string failureStatus = "Failure";
        private static bool logRequired = false;
        private static bool hasError = false;

        private static void LogXMLMsg(string msgXml)
        {
            if (logRequired || hasError)
            {
                try
                {

                    string logFolderPath = Path.GetTempPath();
                    StreamWriter log;
                    if (!File.Exists(logFolderPath + "TypeLogFileNameHere.txt"))
                        log = new StreamWriter(logFolderPath + "TypeLogFileNameHere.txt");
                    else
                        log = File.AppendText(logFolderPath + "TypeLogFileNameHere.txt");

                    log.WriteLine("==================================================================================================");
                    log.WriteLine("Date Time:" + DateTime.Now);
                    log.WriteLine("Msg XML:" + msgXml);
                    log.Close();
                }
                catch (Exception ex)
                {
                    //Code should not reach here.
                    //EventLog m_EventLog = new EventLog("");
                    //m_EventLog.Source = "MDM Event Log";
                    //m_EventLog.WriteEntry(ex.Message, EventLogEntryType.FailureAudit);

                }
            }
        }
        private static string UpdateErrorInformation(string xmlString, string exceptionMessage, string errorCode)
        {
// Here I have created one xml file with my schema to store the error info and send over the mail 
// You can use your xml format or schema for recording error info
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(xmlString);
            string errorDescXpath = "MSG/HeaderCommon/ErrorDescription";
            string errorCodeXpath = "MSG/HeaderCommon/ErrorCode";
            string transportStatusXpath = "MSG/HeaderCommon/TransportStatus";
            xmlDoc.SelectNodes(errorDescXpath).Item(0).InnerXml = exceptionMessage;
            xmlDoc.SelectNodes(errorCodeXpath).Item(0).InnerXml = errorCode;
            xmlDoc.SelectNodes(transportStatusXpath).Item(0).InnerXml = failureStatus;
            return xmlDoc.InnerXml;
        }
        private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
        {
            bool result = false;
            if (cert.Subject.ToUpper().Contains("Fully Qualified Domain Name e.g Xyz.Abc.com"))
            {
                result = true;
            }

            return result;
        }
        private static string Serialize(object dataToSerialize)
        {
            if (dataToSerialize == null) return null;

            using (StringWriter stringWriter = new StringWriter())
            {
                var serializer = new XmlSerializer(dataToSerialize.GetType());
                serializer.Serialize(stringWriter, dataToSerialize);
                return stringWriter.ToString();
            }
        }


        /// <summary>
        /// Get client certificate from windows key store for current application
        /// </summary>
        /// <returns></returns>
        public static X509Certificate2 GetCertificate()
        {
            X509Certificate2 cert = null;
            X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindByThumbprint, "ProvideYourClientCertificateThumbprint", false);
            if (certs.Count == 0)
            {
                throw new Exception("Client Certificate not found in current application's personal key store");
            }
            cert = certs[0];
            return cert;
        }


        //Call biztalk method
// Note: certPath means Your certificate ThumbPrint
        public static string SendXmlMessagetoBiztalkAsync(string msgXml, bool enableCertificate, string certPath)
        {
            LogXMLMsg("Msg Received by DLL : " + msgXml);
         

            try
            {

                // var serializer = new XmlSerializer(typeof(FDIService.MSG));
                // XDocument xmlDoc = XDocument.Parse(msgXml);

                // var message = from xml in xmlDoc.Descendants("MSG")
                //   select serializer.Deserialize(xml.CreateReader()) as FDIService.MSG;
                string messageCommon = msgXml;

                string WcfURLProtocol = "https";

                if (!WcfURLProtocol.Contains("https"))
                {
                    WSHttpBinding binding = new WSHttpBinding(SecurityMode.None);
                    binding.MaxReceivedMessageSize = 2147483647;
                    binding.SendTimeout = TimeSpan.FromMinutes(5);
                    Uri serviceUri = new Uri("https://dtraflon2k112.global.trafigura.com/FDI_Service/FDIService.svc");
                    EndpointIdentity identity = EndpointIdentity.CreateDnsIdentity("Fully Qualified Domain Name e.g Xyz.Abc.com");
                    EndpointAddress address = new EndpointAddress(serviceUri);

                    FDIService.FDIServiceClient client = new FDIService.FDIServiceClient(binding, address);
                    //client.SendRequest(ref messageCommon);
                    client.GetRegionbyCompany("cco");
                    hasError = false;
                    return Serialize(messageCommon);
                }
                else
                {
                    WSHttpBinding binding = new WSHttpBinding(SecurityMode.Transport);
                    if (enableCertificate == true)
                    {
                        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
                    }
                    else
                    {
                        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
                        binding.Security.Message.NegotiateServiceCredential = true;
                    }
                    binding.MaxReceivedMessageSize = 2147483647;
                    binding.UseDefaultWebProxy = false;
                    binding.SendTimeout = TimeSpan.FromMinutes(5);
                    Uri serviceUri = new Uri("https://dtraflon2k112.global.trafigura.com/FDI_Service/FDIService.svc");
                    EndpointIdentity identity = EndpointIdentity.CreateDnsIdentity("Fully Qualified Domain Name e.g Xyz.Abc.com");
                    EndpointAddress address = new EndpointAddress(serviceUri);


                    FDIService.FDIServiceClient client = new FDIService.FDIServiceClient(binding, address);

                    if (enableCertificate)
                    {
                        ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);
                        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
                        if (!Path.IsPathRooted(certPath)) // If you want to determine if a string contains a relative or absolute folder / file path, you can use the System.IO.Path.IsPathRooted function:
                        {
                            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
                            store.Open(OpenFlags.ReadOnly);
                            X509Certificate2Collection objcertificates = store.Certificates.Find(X509FindType.FindByThumbprint, certPath, false);
                            store.Close();
                            if (objcertificates.Count == 0)
                            {
                                hasError = true;
                                LogXMLMsg("Exception Async : " + "SSL Certificate not found in local machine / personal key store using thumbprint : " + certPath);
                                return UpdateErrorInformation(msgXml, "SSL Certificate not found in local machine / personal key store using thumbprint : " + certPath, "SSL Certificate not found in local machine / personal key store. Please contact administrator.");
                            }
                            X509Certificate2 cert1 = new X509Certificate2();
                            cert1 = objcertificates[0];
                            //var cert = objcertificates[0];
                            client.ClientCredentials.ClientCertificate.Certificate = cert1;
                            //client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "TypeHereYourCertificateThumbprint");
                        }
                        else
                        {
                            X509Certificate2 cert = new X509Certificate2(certPath);

                            if (cert == null)
                            {
                                hasError = true;
                                LogXMLMsg("Exception Async : " + "SSL certificate file: " + certPath + " not exist or invalid.");
                                return UpdateErrorInformation(msgXml, "SSL certificate file: " + certPath + " not exist or invalid.", "SSL Certificate is not found. Please contact administrator.");
                            }
                            client.ClientCredentials.ClientCertificate.Certificate = cert;
                        }
                    }
                    //  System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;                                   
                    // client.SendRequest(ref messageCommon);
                    FDIService.RegionByCompanyDC rbcdc = null;

                    rbcdc=client.GetRegionbyCompany("PEG");
                    Console.WriteLine("Company : " + rbcdc.Company);
                    Console.WriteLine("Description : " + rbcdc.Description);
                    Console.WriteLine("ExtensionData : " + rbcdc.ExtensionData);
                    Console.WriteLine("Region : " + rbcdc.Region);
                    Console.WriteLine("Result : " + rbcdc.Result);
                    hasError = false;
                    return Serialize(messageCommon);
                }

            }
            catch (System.Xml.XmlException xmlException)
            {
                hasError = true;
                LogXMLMsg("Exception Async : " + xmlException.Message);
                return UpdateErrorInformation(msgXml, xmlException.Message, "Input XML message is not in correct format.");
            }
            catch (System.Net.WebException webException)
            {
                hasError = true;
                LogXMLMsg("Exception Async : " + webException.Message);
                return UpdateErrorInformation(msgXml, webException.Message, "An error occurred while calling BizTalk service. Please contact administrator.");
            }
            catch (System.ServiceModel.ServiceActivationException serviceActivationException)
            {
                hasError = true;
                LogXMLMsg("Exception Async : " + serviceActivationException.Message);
                return UpdateErrorInformation(msgXml, serviceActivationException.Message, "BizTalk service is not running. Please contact administrator.");
            }

            catch (TimeoutException timeProblem)
            {
                hasError = true;
                LogXMLMsg("Exception Async : " + timeProblem.Message);
                return UpdateErrorInformation(msgXml, timeProblem.Message, "BizTalk service operation timed out.");
            }
            catch (FaultException faultEx)
            {
                hasError = true;
                LogXMLMsg("Exception Async : " + faultEx.Message);
                return UpdateErrorInformation(msgXml, faultEx.Message, "An unknown SOAP fault exception was received from BizTalk service.");
            }
            // Standard communication fault handler.
            catch (CommunicationException commProblem)
            {
                hasError = true;
                LogXMLMsg("Exception Async : " + commProblem.Message);
                return UpdateErrorInformation(msgXml, commProblem.Message, "There was a communication problem occurred while accessing BizTalk service.");

            }
            catch (Exception exception)
            {
                hasError = true;
                LogXMLMsg("Exception Async : " + exception.Message);
                return UpdateErrorInformation(msgXml, exception.Message, "Error occurred while processing the current Transaction on Biztalk Integration library layer.");
            }

        }
    }
}


Step 2: To Consume this class we need the entry point of the project i.e. Main method
Here I have created the Program class to consume it.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WCFClientApp
{
    class Program
    {
        static void Main(string[] args)
        {
// Method prototype is 1st Param is XmlMsg format to store error info
//2nd Param Boolean value for IsCertificate mean do you want to provide certificate
//3rd Param is Certificate ThumbPrint
            string outmsg = CallWcfServiceWithCertificate.SendXmlMessagetoBiztalkAsync("xmlmsg", true, "TypeHereYourCertificateThumbprint");
            Console.WriteLine(outmsg);

            Console.ReadKey();
        }
    }
}


Step 3: Important for installing the Client certificate into window store
Goto Windows Search and type for Run and then type into Run window as MMC 
it will open mmc window then follow the procedure

Steps: procedure 1
Step 1 Run the MMC with different user account and provide the below details
Eg. User Name : svc_biztalk_dev password :
Step 2 Goto File menu and select
1


3 select certificate and click on add  --- ok 



4 select my user account  and click finish



Step 5  Import the certificate into Personal, TrustedPeople


Step 6 click next


Step 7 Click on Browse and select certificate which you want to import and next



Step 8 it will ask password for certificate and click next and finish.




Steps: procedure 2
Step 1 Run the MMC as administrator 
Step 2 Goto File menu and select



3 select certificate and click on add  --- ok 



4 select Computer account  and click finish




Step 5 Import certificate into Personal, TrustedPeople and Other People


Step 6  click next


Step 7 Click on Browse and select certificate which you want to import and next



Step 8 it will ask password for certificate and click next and finish.


Note : How to get thumbprint 
Goto MMC and 

No comments:

Post a Comment