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

領悟 Web 設計模式:從傳統 WebForm 到 MVC 架構思維

     編輯:關於ASP.NET

ASP.NET WebForm 雖提供事件驅動模型,但許多開發者仍沿用腳本式寫法,導致邏輯與呈現耦合。本文透過簡單的「Portal-Subject」主從資料查詢範例,對比傳統 WebForm 寫法與模式化架構 (Repository、Service、Controller),展示關注點分離帶來的可測試性與維護性。

傳統 WebForm 寫法 (耦合版)

// WebForm.aspx.cs
private void Page_Load(...) {
    if (!IsPostBack) {
        using (var conn = new SqlConnection(cfg["ConnStr"])) {
            var da = new SqlDataAdapter("SELECT * FROM Portal", conn);
            var ds = new DataSet(); da.Fill(ds);
            dropDownList.DataSource = ds;
            dropDownList.DataTextField = "PortalName";
            dropDownList.DataValueField = "PortalId";
            dropDownList.DataBind();
        }
    }
}
private void button_Click(...) {
    using (var conn = new SqlConnection(cfg["ConnStr"])) {
        string sql = string.Format("SELECT * FROM Subject WHERE PortalId = {0}", dropDownList.SelectedValue);
        var da = new SqlDataAdapter(sql, conn);
        var ds = new DataSet(); da.Fill(ds);
        dataGrid.DataSource = ds; dataGrid.DataBind();
    }
}

缺點:SQL 散落事件中、連線字串硬編碼、無法單元測試、邏輯無法重用、修改 Schema 需改多處。

模式化重構 (三層 + Repository)

資料實體

public class Portal { public int Id { get; set; } public string Name { get; set; } }
public class Subject { public int Id { get; set; } public string Title { get; set; } public int PortalId { get; set; } }

Repository 介面與實作


public interface IPortalRepository { IEnumerable GetAll(); }
public interface ISubjectRepository { IEnumerable GetByPortal(int portalId); }

public class SqlPortalRepository : IPortalRepository {
    private readonly string _connStr;
    public SqlPortalRepository(string connStr) { _connStr = connStr; }
    public IEnumerable GetAll() {
        using (var conn = new SqlConnection(_connStr))
        using (var cmd = new SqlCommand("SELECT Id, Name FROM Portal", conn)) {
            conn.Open();
            using (var rd = cmd.ExecuteReader())
                while (rd.Read()) yield return new Portal { Id = rd.GetInt32(0), Name = rd.GetString(1) };
        }
    }
}

Service 層 (可選,封裝商業規則)


public class PortalService {
    private readonly IPortalRepository _repo;
    public PortalService(IPortalRepository repo) { _repo = repo; }
    public IEnumerable GetPortals() => _repo.GetAll();
}

WebForm 作為 Controller/View


// Global.asax 或 IoC 容器註冊
// Application["PortalService"] = new PortalService(new SqlPortalRepository(cfg["ConnStr"]));

// WebForm.aspx.cs
private PortalService Service => (PortalService)Application["PortalService"];

protected void Page_Load(...) {
    if (!IsPostBack) {
        dropDownList.DataSource = Service.GetPortals();
        dropDownList.DataTextField = "Name";
        dropDownList.DataValueField = "Id";
        dropDownList.DataBind();
    }
}
protected void btnQuery_Click(...) {
    var subjectRepo = (ISubjectRepository)Application["SubjectRepo"];
    dataGrid.DataSource = subjectRepo.GetByPortal(int.Parse(dropDownList.SelectedValue));
    dataGrid.DataBind();
}

進階:MVP / MVC 框架

  • Web Forms MVP:Presenter 處理邏輯,View 介面只負責繫結事件與顯示,單元測試針對 Presenter。
  • ASP.NET MVC:Controller 接收請求、呼叫 Service/Repository、傳遞 Model 給 View (Razor),天然關注點分離、支援 TDD、URL 路由友好。

遷移建議

  1. 新專案優先選擇 ASP.NET Core MVC / Razor Pages。
  2. 舊專案逐步引入 Repository/Service 層,將 SQL 移出代碼後置頁面。
  3. 建立單元測試專案,針對 Service/Repository 測試,WebForm 邏輯逐步縮減。
  4. 使用 IoC 容器 (Autofac、Unity、內建 DI) 管理依賴關係。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved