1

I have two projects running locally. One is a portal and the other is a WebAPI. The portal uses a WebAPI client to upload files to the server (currently, it is uploaded on a local directory). Whenever I try to upload a file from the portal, a client method gets fired that posts the file data to an API endpoint using a PostAsync method. However, whenever I reach the PostAsync, a Could not establish trust relationship for the SSL/TLS secure channel exception gets thrown.

What I tried

  • I tried adding ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; in the Global.asax.cs file in the WebAPI project, int the portal project's Global.asax.cs, and before the initialization of my HttpClient in the client project
  • I tried adding <authentication mode="None" /> in the web.config file of the WebAPI project

None of those solutions alone or together worked. From my research online, some say that a way around that would be to add ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;, but that has some security flaws.

Can someone shed some light on how I can get over this? I am not sure if I should install a specific certificate for the API and register it in the Portal project or what should I do.

Here is my current code:

Portal Upload Document Controller (I call the client using _client)

    public class UploadApplicationController : Controller
        {
            public string strMessage = "";
            EcommUtilityServiceClient _client = new EcommUtilityServiceClient(ConfigurationManager.AppSettings["baseURI"]);
    
           [HttpPost]
            public ActionResult Upload(HttpPostedFileBase file, UploadApplicationModel model)
            {
                Stream fStream = file.InputStream;
    
                string[] extensions = file.FileName.Split('.');
                string fileExtension = extensions[extensions.Length - 1].ToString();
                byte[] fileContent = new byte[fStream.Length];
                int numBytesToRead = (int)fStream.Length;
                int numBytesRead = 0;
    
                while (numBytesToRead > 0)
                {
                    int n = fStream.Read(fileContent, 0, numBytesToRead);
    
                    if (n == 0)
                    {
                        break;
                    }
    
                    numBytesRead += n;
                    numBytesToRead -= n;
                }
                numBytesToRead = fileContent.Length;
    
                PostedUploadFileModel modelToPost = new PostedUploadFileModel()
                {
                    TaxId = ((User)User).TaxID,
                    FileName = file.FileName,
                    FileExtenstion = fileExtension,
                    FileContent = fileContent,
                    NumBytesToRead = numBytesToRead
                };
    
                fStream.Close();
    
                var response = _client.UploadDocument(modelToPost);
    
    
                return View("UploadApplication", model);
            }
    }

Client UploadDocument Method (exceptions get thrown on response = _client.PostAsync(url, form).Result;):

 public class EcommUtilityServiceClient : ServiceClientBase, IEcommUtilityServiceClient
    {
        public EcommUtilityServiceClient(string endpointAddress) : base(endpointAddress)
        {

        }

        public async Task<HttpResponseMessage> UploadDocument(PostedUploadFileModel fileModel)
        {

            string url = $"api/UploadDocuments/UploadDocument";
            string fileTempDirectoryPath = "C:\\FilesToUpload\\";
            string fileCreatePath = fileTempDirectoryPath + fileModel.FileName + "." + fileModel.FileExtenstion;
            HttpResponseMessage response = null;
            MultipartFormDataContent form = new MultipartFormDataContent();

            try
            {
                Directory.CreateDirectory(fileTempDirectoryPath);
                FileStream receivedFile = new FileStream(fileCreatePath, FileMode.Create, FileAccess.Write);

                receivedFile.Write(fileModel.FileContent, 0, fileModel.NumBytesToRead);
                receivedFile.Close();

                var fileContent = new StreamContent(new FileStream(fileCreatePath, FileMode.Open));
                fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");

                var taxIdContent = new StringContent(fileModel.TaxId);
                taxIdContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");

                form.Add(taxIdContent, "TaxID", "TaxID");
                form.Add(fileContent, "FileToUpload", Path.GetFileName(fileCreatePath));

                response = _client.PostAsync(url, form).Result;
                response.EnsureSuccessStatusCode();

                Directory.Delete(fileTempDirectoryPath, true);
            }
            catch (Exception e)
            {

                Console.WriteLine("Error while parsing file: " + e.Message);
            }

            return response;
        }
}

Client's ServiceBase.cs class:

        protected static HttpClient _client;
        protected HttpMessageHandler _handler;

        public ServiceClientBase(string endpointAddress)
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            _client = new HttpClient();
            _client.BaseAddress = new Uri(endpointAddress);
        }

The WebAPI UploadDocument endpoint:


            [HttpPost]
            [Route("api/UploadDocuments/UploadDocument")]
            public async Task<HttpResponseMessage> UploadDocument()
            {
    
                string destinationPath = ConfigurationManager.AppSettings["filePath"];
                string message;
                HttpResponseMessage result = null;
                HttpRequest httpRequest = HttpContext.Current.Request;
                UploadDocumentModel model = new UploadDocumentModel();
    
                if (httpRequest.Files.Count > 0)
                {
                    foreach (string file in httpRequest.Files)
                    {
                        var postedFile = httpRequest.Files[file];
    
                        if (postedFile.FileName.Equals("TaxID")) // Check for the posted TaxID
                        {
                            var fileLen = postedFile.ContentLength;
                            byte[] input = new byte[fileLen];
    
    
                            var stream = postedFile.InputStream;
                            stream.Read(input, 0, fileLen);
    
                            model.TaxID = Encoding.UTF8.GetString(input, 0, input.Length);
                            result = Request.CreateResponse(HttpStatusCode.BadRequest, model);
                        }
                        else
                        {
                            model.FileName = postedFile.FileName;
                            model.ReceivedDate = DateTime.Now.ToString();
                            result = Request.CreateResponse(HttpStatusCode.Created, model);

                        }
                return result;
            }

Global.asax.cs file for the WebAPI:

public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        }
    }

What am I doing wrong?

Hussam Ahmed
  • 413
  • 1
  • 5
  • 17
  • Try the ServerCertificateValidationCallback option you mentioned and see if the SSL message goes away. It will help you towards the next steps. If the problem is on the other end's certificates being invalid, there's little you can do locally. – vhoang Jan 26 '21 at 20:51
  • 1
    The problem is a combination of your Operating System, the version of Net being used, and the type of certificate. TLS 1.0 and 1.1 are obsolete. So the certificate has to be an encryption mode that is support by TLS 1.2 or 1.3 (see : https://en.wikipedia.org/wiki/Transport_Layer_Security). Then Microsoft made changes to newer versions of Net to use Operating System to do TLS instead of the Net Library. So older versions of Net do not support TLS 1.2/1.3. Newer versions Net uses operating System DLLS and your operating system may not support 1.2/1.3. – jdweng Jan 26 '21 at 21:01
  • See [here](https://stackoverflow.com/questions/703272/could-not-establish-trust-relationship-for-ssl-tls-secure-channel-soap) for a good discussion of options if it turns out to be a certificate validation problems. – vhoang Jan 26 '21 at 21:08

0 Answers0