How to rewrite Web Api with best practice and best performance?

ahmed salah 3,216 Reputation points
2021-08-28T14:57:10.393+00:00

I work on asp.net core 2.2 web API using C# language

I need to rewrite function below with best syntax and with best practice

web API below get Excel file from upload and return Excel file

it working without any issue but I need to rewrite it with best syntax and practice

some points I need to changes :

concatenate path is best thing using

are streaming using correctly

are memory copying file is correct

[HttpPost, DisableRequestSizeLimit]
    [Route("Upload")]
    public IActionResult Upload()
    {
        try
        {
            var DisplayFileName = Request.Form.Files[0];
            string fileName = DisplayFileName.FileName.Replace(".xlsx", "-") + Guid.NewGuid().ToString() + ".xlsx";
            string Month = DateTime.Now.Month.ToString();
            string DirectoryCreate = myValue1 + "\\" + Month + "\\" + fileName;
            string exportDirectory = myValue2 + "\\" + Month;
            string exportPath = myValue2 + "\\" + Month + "\\" + fileName;
            string FinalPath = exportPath;

            if (!Directory.Exists(DirectoryCreate))
            {
                Directory.CreateDirectory(DirectoryCreate);

            }
            if (!Directory.Exists(exportDirectory))
            {
                Directory.CreateDirectory(exportDirectory);

            }
            CExcel ex = new CExcel();
            if (DisplayFileName.Length > 0)
            {
                var filedata = ContentDispositionHeaderValue.Parse(Request.Form.Files[0].ContentDisposition).FileName.Trim('"');
                var dbPath = Path.Combine(DirectoryCreate, fileName);

                using (var stream = new FileStream(dbPath, FileMode.Create))
                {
                    Request.Form.Files[0].CopyTo(stream);
                    stream.Flush();
                    stream.Close();
                }
                GC.Collect();
                string error = "";
                int rowCount = 0;
                string inputTemplatePath = "";

                var InputfilePath = System.IO.Path.Combine(GetFilesDownload, "DeliveryGeneration_Input.xlsx");
                bool areIdentical = ex.CompareExcel(dbPath, InputfilePath, out rowCount, out error);
                if (areIdentical == true)
                {
                    List<InputExcel> inputexcellist = new List<InputExcel>();
                    inputexcellist = ex.Import(dbPath);
                    List<string> mods = new List<string>();
                    mods = inputexcellist.Select(x => x.ModuleName).Distinct().ToList();
                    var OutputfilePath = System.IO.Path.Combine(GetFilesDownload, "DeliveryGeneration_Output.xlsx");
                    if (System.IO.Directory.Exists(Path.Combine(exportDirectory, fileName)))
                    {
                        throw new Exception("Ok so the error message IS right.");
                    }
                    System.IO.File.Copy(OutputfilePath, Path.Combine(exportDirectory, fileName), true);

                    SqlConnection con;
                    foreach (var m in mods)
                    {
                        List<InputExcel> inputmodulelist = new List<InputExcel>();
                        inputmodulelist = inputexcellist.Where(x => x.ModuleName == m).ToList();
                        var dtimport = DatatableConversion.ToDataTable(inputmodulelist);
                        DataTable dtexport = new DataTable();
                        dtexport = _deliveryService.LoadExcelToDataTable(_connectionString, dtimport);
                        ex.Export(dtexport, m, exportPath);

                    }
                }
                var memory2 = new MemoryStream();
                using (var stream = new FileStream(exportPath, FileMode.Open))
                {
                    stream.CopyTo(memory2);
                }
                memory2.Position = 0;

                return File(memory2, "text/plain", Path.GetFileName(exportPath));

            }
            else
            {
                return BadRequest();
            }
        }
        catch (Exception ex)
        {
            return StatusCode(500, $"Internal server error: {ex}");
        }
    }
Developer technologies | ASP.NET | ASP.NET Core
Developer technologies | ASP.NET | Other
Developer technologies | C#
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 77,686 Reputation points Volunteer Moderator
    2021-08-28T15:46:47.92+00:00

    You should be using async file and database calls, or you will limit scaling.

    It also looks like you write a file, then read it back. And why the extra memory copy?


  2. Anonymous
    2021-08-30T08:54:11.353+00:00

    Hi @ahmed salah ,

    can you please see me how to use async task on web api above

    To convert the Upload method to the async method, you can refer the following sample:

    in the service methods: from your code, since you are using _deliveryService to call the database, you can change the code as below:

    public interface IDeliveryService  
    {  
        Task<string> LoadExcelToDataTableAsync(string connectionstring, string inport);  
    }  
    
    public class DeliveryService : IDeliveryService  
    {  
        private readonly ApplicationDbContext _context;  
    
        public DeliveryService(ApplicationDbContext context)  
        {  
            _context = context;  
        }  
    
        public async Task<string> LoadExcelToDataTableAsync(string connectionstring, string inport)  
        {  
            // do something  
    
            //access the database via _context.  
    
            return await Task.FromResult<string>("OK");  
        }  
    }  
    

    In the above code, I access the database via EF code, more detail you can refer this article.

    Then, in the controller, the code as below:

        private readonly IDeliveryService _deliveryService;  
        public HomeController(IDeliveryService deliveryService)  
        {   
            _deliveryService = deliveryService;  
        }  
    
        public async Task<IActionResult> UploadAsync()  
        {   
            var result = await _deliveryService.LoadExcelToDataTableAsync("connection", "inport");  
            return View();  
        }  
    

    More detail information about asynchronous programming, see Asynchronous programming with async and await.

    Besides, here is an article about ASP.NET Core Performance Best Practices, you can refer it.


    If the answer is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,
    Dillion


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.