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}");
        }
    }
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,162 questions
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,254 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,240 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 55,686 Reputation points
    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. Zhi Lv - MSFT 32,011 Reputation points Microsoft Vendor
    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