How to call file upload (IFormFile) api in ASP.NET Core web api project from ASP.NET webform using WebClient?

5.7k Views Asked by At

I have created one API in ASP.NET Core 3.1 project for file uploading. This api working fine when I called api from Postman or any other .NET Core project using HttpClient. But I am unable to call this api from Webform using WebClient.

[HttpPost("Upload")]
public IActionResult Upload([FromForm] IFormFile fileUpload)
{
    ResponseViewModel responseModel = new ResponseViewModel();
    try
    {       
        if (fileUpload == null)
        {
            responseModel.Message = "Please select file.";
            return BadRequest(responseModel);
        }

        //file upload to temp folder
        string tempFilPathWithName = Path.GetTempFileName();
        using (FileStream file = System.IO.File.OpenWrite(tempFilPathWithName))
        {
            fileUpload.CopyTo(file);
        }
        UploadFile uploadFile = new UploadFile()
        {
            FileName = fileUpload.FileName,
            TempFilPathWithName = tempFilPathWithName
        };

        responseModel.Model = uploadFile;
        responseModel.Message = "File successfully uploaded";
        return Ok(responseModel);
    }
    catch (Exception ex)
    {
        responseModel.ExceptionMessage = ex.ToString();
        responseModel.Message = "File upload failed.";
    }
    return BadRequest(responseModel);
}

public class ResponseViewModel
{   
    public object Model { get; set; }
    public string ExceptionMessage { get; set; }
    public string Message { get; set; } 
}

After uploading file on server (where ASP.NET Core wep api project deploy) I will getting response like: uploaded file path and name.

2

There are 2 best solutions below

2
Md Farid Uddin Kiron On

This api working fine when I called api from Postman or any other .NET Core project using HttpClient. But I am unable to call this api from Webform using WebClient.

It would be nicer if you could share your request code snippet in details but apart from this you could achieve the using HttpClient.

In addition to this, sending file request from ASP.NET webform project you would require MultipartFormDataContent so that you can implement your requirement accordingly.

After uploading file on server (where ASP.NET Core wep api project deploy) I will getting response like: uploaded file path and name.

Let's have a look on a quick demonstration how we can efficiently implement that in action:

File Upload From ASP.NET webform To Asp.net Core Web API:

public partial class Contact : Page
    {

        protected void Page_Load(object sender, EventArgs e)
        {
            RegisterAsyncTask(new PageAsyncTask(UploadFileFromAspDotNetWebFormToWebAPI));
        }
            
        static readonly HttpClient client = Client.GetClient();
        private async Task UploadFileFromAspDotNetWebFormToWebAPI()
        {
            //Bind your file location
            var readFileData = System.IO.File.ReadAllBytes(@"D:\Md Farid Uddin Resume.pdf");
            //Create Multipart Request
            var formContent = new MultipartFormDataContent();
            formContent.Add(new StreamContent(new MemoryStream(readFileData)), "fileUpload", "fileUpload");
            var response = await client.PostAsync("https://localhost:7132/api/Upload/UploadFromWebFromToWebAPI", formContent);
            if (response.IsSuccessStatusCode)
            {
                var readResponse = await response.Content.ReadAsStringAsync();
                ResponseViewModel readApiResponse = JsonConvert.DeserializeObject<ResponseViewModel>(readResponse);
            }

        }
       
    }

Note: Important point to keep in find here, in StreamContent you should match request parameter as same as your controller parameter defination. In your scenario, your controller name is fileUpload; Thus, it should be matched exactly and last one is file name you want to pass which is mandatory and I kept that same but you can put anything. Otherwise, request would not reach to endpoint.

Response Model:

public class ResponseViewModel
{   
    public object Model { get; set; }
    public string ExceptionMessage { get; set; }
    public string Message { get; set; } 
}

Output:

enter image description here

Last but not least, for API code snippet I have tested with your sample but I personally prefer following way and I like to keep my files under wwwroot.

enter image description here

API File Operation:

        [HttpPost("UploadFromWebFromToWebAPI")]
        public async Task<ActionResult> UploadFromWebFromToWebAPI([FromForm] IFormFile formFile)
        {

            if (formFile.FileName == null)
            {
                return BadRequest();
            }
            var path = Path.Combine(_environment.WebRootPath, "Files/", formFile.FileName);


            using (FileStream stream = new FileStream(path, FileMode.Create))
            {
                await formFile.CopyToAsync(stream);
                stream.Close();
            }
            UploadFile uploadFile = new UploadFile()
            {
                FileName = formFile.FileName,
                TempFilPathWithName = path
            };


            var responseViewModel = new ResponseViewModel();
            responseViewModel.Model = uploadFile;
            responseViewModel.Message = "File Uploaded...";
            responseViewModel.ExceptionMessage = "N/A";
            return Ok(responseViewModel);

        }

Note: If you would like to know more details on it you could check our official document here.

0
Prashant Girase On

Finally, I found the solution to my question. Using the below code we call file upload (IFormFile) API in ASP.NET Core web API project from ASP.NET webform using WebClient.

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace WebApplication
{
    public partial class User : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                string filePath = @"C:\temp\excelsheet.xlsx";
                string apiToken = "BearerToken";
                
                NameValueCollection headers = new NameValueCollection();
                headers.Add(HttpRequestHeader.Authorization.ToString(), $"Bearer {apiToken}");
                List<FileInfo> files = new List<FileInfo>() { new FileInfo(filePath) };
                
                MultiPartFormUpload multiPartFormUpload = new MultiPartFormUpload();
                MultiPartFormUpload.UploadResponse response = multiPartFormUpload.Upload("https://localhost:5001/api/FileUpload/Upload", headers, new NameValueCollection() { }, files);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }       
    }
    
    public class MultiPartFormUpload
    {
        public class MimePart
        {
            NameValueCollection _headers = new NameValueCollection();
            byte[] _header;

            public NameValueCollection Headers
            {
                get { return _headers; }
            }

            public byte[] Header
            {
                get { return _header; }
            }

            public long GenerateHeaderFooterData(string boundary)
            {
                StringBuilder stringBuilder = new StringBuilder();

                stringBuilder.Append("--");
                stringBuilder.Append(boundary);
                stringBuilder.AppendLine();
                foreach (string key in _headers.AllKeys)
                {
                    stringBuilder.Append(key);
                    stringBuilder.Append(": ");
                    stringBuilder.AppendLine(_headers[key]);
                }
                stringBuilder.AppendLine();

                _header = Encoding.UTF8.GetBytes(stringBuilder.ToString());

                return _header.Length + Data.Length + 2;
            }

            public Stream Data { get; set; }
        }

        public class UploadResponse
        {
            public UploadResponse(HttpStatusCode httpStatusCode, string responseBody)
            {
                HttpStatusCode = httpStatusCode;
                ResponseBody = responseBody;
            }

            public HttpStatusCode HttpStatusCode { get; set; }

            public string ResponseBody { get; set; }
        }

        public UploadResponse Upload(string url, NameValueCollection requestHeaders, NameValueCollection requestParameters, List<FileInfo> files)
        {
            using (WebClient client = new WebClient())
            {
                List<MimePart> mimeParts = new List<MimePart>();

                try
                {
                    foreach (string key in requestHeaders.AllKeys)
                    {
                        client.Headers.Add(key, requestHeaders[key]);
                    }

                    foreach (string key in requestParameters.AllKeys)
                    {
                        MimePart part = new MimePart();

                        part.Headers["Content-Disposition"] = "form-data; name=\"" + key + "\"";
                        part.Data = new MemoryStream(Encoding.UTF8.GetBytes(requestParameters[key]));

                        mimeParts.Add(part);
                    }

                    foreach (FileInfo file in files)
                    {
                        MimePart part = new MimePart();
                        string name = "fileUpload"; //file.Extension.Substring(1);
                        string fileName = file.Name;

                        part.Headers["Content-Disposition"] = "form-data; name=\"" + name + "\"; filename=\"" + fileName + "\"";
                        part.Headers["Content-Type"] = "application/octet-stream";

                        part.Data = new MemoryStream(File.ReadAllBytes(file.FullName));

                        mimeParts.Add(part);
                    }

                    string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
                    client.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=" + boundary);

                    long contentLength = 0;

                    byte[] _footer = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");

                    foreach (MimePart mimePart in mimeParts)
                    {
                        contentLength += mimePart.GenerateHeaderFooterData(boundary);
                    }

                    byte[] buffer = new byte[8192];
                    byte[] afterFile = Encoding.UTF8.GetBytes("\r\n");
                    int read;

                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        foreach (MimePart mimePart in mimeParts)
                        {
                            memoryStream.Write(mimePart.Header, 0, mimePart.Header.Length);

                            while ((read = mimePart.Data.Read(buffer, 0, buffer.Length)) > 0)
                                memoryStream.Write(buffer, 0, read);

                            mimePart.Data.Dispose();

                            memoryStream.Write(afterFile, 0, afterFile.Length);
                        }

                        memoryStream.Write(_footer, 0, _footer.Length);
                        var ss = memoryStream.ToArray();
                        byte[] responseBytes = client.UploadData(url, memoryStream.ToArray());
                        string responseString = Encoding.UTF8.GetString(responseBytes);
                        return new UploadResponse(HttpStatusCode.OK, responseString);
                    }
                }
                catch (Exception ex)
                {
                    foreach (MimePart part in mimeParts)
                        if (part.Data != null)
                            part.Data.Dispose();

                    if (ex.GetType().Name == "WebException")
                    {
                        WebException webException = (WebException)ex;
                        HttpWebResponse response = (HttpWebResponse)webException.Response;
                        string responseString;

                        using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
                        {
                            responseString = reader.ReadToEnd();
                        }

                        return new UploadResponse(response.StatusCode, responseString);
                    }
                    else
                    {
                        throw;
                    }
                }
            }
        }
    }
}