我們把昨天的寫入檔案功能抽成一個獨立靜態方法,減少Action負責的邏輯,在其他地方若也用到寫度檔案功能,抽成獨立方法,也能增加程式碼重複利用性。
這邊我在專案中建立一個Helpers資料夾,專門放這種重複利用的功能,並在裡面新增FileHelper.cs,並建立Writer()方法,將寫入檔案功能移動到裡面,寫如完畢後回傳一個資料庫File類別。
public class FileHelper
{
public static async Task<Models.File> WriterAsync(IFormFile file)
{
//取得使用者上傳檔案的原始檔名
var fileOriginName = Path.GetFileName(file.FileName);
//取原始檔名中的副檔名
var fileExt = Path.GetExtension(fileOriginName);
//為避免使用者上傳的檔案名稱發生重複,重新給一個亂數名稱
var fileNewName = Path.GetRandomFileName();
//指定要寫入的路徑、檔名和副檔名
var filePath = "/data/" + fileNewName + fileExt;
//將使用者上傳的檔案寫入到指定路徑
await using (var stream = System.IO.File.Create(filePath))
{
//執行寫入
await file.CopyToAsync(stream);
}
var newFile = new Models.File()
{
Id = Guid.NewGuid().ToString(),
Name = fileNewName + fileExt
};
return newFile;
}
}
移動完之後,我的Action會變得比較乾淨如下
[HttpPost]
public async Task<IActionResult> AddProduct(AddProductViewModel productViewModel)
{
if (ModelState.IsValid)
{
var file = await FileHelper.WriterAsync(productViewModel.File);
var last = _context.Product.OrderByDescending(d => d.Id).FirstOrDefault();
var product = new Product()
{
Id = last.Id + 1,
Name = productViewModel.Name,
FileId = file.Id
};
_context.File.Add(file);
_context.Product.Add(product);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(productViewModel);
}
在撰寫MVC的過程中,單純只分M、V、C三個大方向責任範圍其實還不夠用,向檔案寫入、信件發送,或是顯示邏輯判斷等等都可以拆成可以重複使用的功能。