首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

使用 View Model 將領域模型與表現層解耦:ASP.NET MVC 最佳實踐

     編輯:關於.NET

MVC 模式中,Model 封裝業務邏輯與資料,View 負責呈現,Controller 協調兩者。實務上,直接將領域模型傳給 View 會導致安全風險 (Over-posting)、顯示邏輯汙染領域模型、介面需求變更波及資料層。引入 View Model (或 Application Model / DTO) 是解決之道。

領域模型 vs. 視圖模型 差異比較

維度領域模型視圖模型
用途表達核心業務規則、不變條件、資料一致性單純服務特定 View 的顯示/輸入需求
結構豐富物件圖、繼承、導航屬性、驗證邏輯內建扁平化、僅含簡單型別 (string, int, DateTime...)、無行為
資料範圍完整業務實體View 所需欄位子集,可能合併多個領域實體
格式差異如:DateTime OrderDate如:int DaysUntilShip (下拉選單天數)、string FormattedDate
安全性含敏感欄位 (IsAdmin, Salary)僅暴露允許編輯/檢視的欄位

三種轉換策略

  1. 直接使用領域模型當 View Model: 簡單 CRUD 可行,但違反關注點分離,長期維護困難。
  2. View Model 包含領域模型屬性: public Customer DomainModel { get; set; },View 透過 Model.DomainModel.Name 存取,仍暴露完整物件圖。
  3. 映射對應 (推薦): 定義獨立 View Model 類別,Controller 負責映射轉換。

為何避免前兩種?

  • Over-posting 攻擊: Model Binder 會嘗試繫結表單所有欄位,駭客可偽造隱藏欄位 (如 IsAdmin=true)。
  • 驗證邏輯耦合: 領域驗證 (如薪資>0) 與介面驗證 (如必填、格式) 混雜。
  • 版本演進風險: 領域模型新增欄位未編譯錯誤,卻可能被惡意繫結。

推薦工具:AutoMapper

自動化領域模型 ↔ View Model 映射,慣例大於配置:

Mapper.CreateMap<Customer, CustomerViewModel>();
var viewModel = Mapper.Map<CustomerViewModel>(domainCustomer);

支援扁平化 (Customer.Address.City → CustomerViewModel.City)、自訂解析器、條件映射等進階功能。

Controller 實作範例

[HttpPost]
public ActionResult Edit(CustomerViewModel viewModel)
{
    if (!ModelState.IsValid) return View(viewModel);

    var customer = _repository.Get(viewModel.Id);
    Mapper.Map(viewModel, customer); // 反向映射更新領域模型
    _repository.Save(customer);
    return RedirectToAction("Index");
}

總結

View Model 是表現層的專用資料契約,隔離領域模型複雜度與安全風險。雖增加映射代碼,但配合 AutoMapper 可大幅降低成本,換取系統長期可維護性與安全性,是專業 ASP.NET MVC 開發的標準做法。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved