保留現有 HTML 結構作為模板,使用 ASP.NET 數據綁定控件(Repeater/ListView/GridView)實現動態渲染。
<!-- 原靜態 HTML (每篇文章重復部分) -->
<div class="post">
<h2>文章標題</h2>
<span class="author">作者名</span>
<span class="time">2024-01-15</span>
<div class="content">文章內容摘要...</div>
</div>
<asp:Repeater ID="rptPosts" runat="server">
<ItemTemplate>
<div class="post">
<h2><%# Eval("Title") %></h2>
<span class="author"><%# Eval("Author") %></span>
<span class="time"><%# Eval("PublishTime", "{0:yyyy-MM-dd}") %></span>
<div class="content"><%# Eval("Summary") %></div>
</div>
</ItemTemplate>
<SeparatorTemplate><hr /></SeparatorTemplate>
<HeaderTemplate><div class="post-list"></HeaderTemplate>
<FooterTemplate></div></FooterTemplate>
</asp:Repeater>
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
BindPosts();
}
}
private void BindPosts() {
string connStr = ConfigurationManager.ConnectionStrings["BlogDB"].ConnectionString;
string sql = "SELECT Title, Author, PublishTime, Summary FROM Posts ORDER BY PublishTime DESC";
using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmd = new SqlCommand(sql, conn))
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd)) {
DataTable dt = new DataTable();
adapter.Fill(dt);
rptPosts.DataSource = dt;
rptPosts.DataBind();
}
}
| 優化點 | 方案 | 代碼示例 |
|---|---|---|
| 分頁 | DataPager + ListView 或 GridView + PagerSettings | ListView 內置分頁支持 |
| 參數化查詢防注入 | SqlParameter | cmd.Parameters.AddWithValue("@cat", category) |
| 緩存減少 DB 壓力 | OutputCache / MemoryCache | [%@ OutputCache Duration="60" VaryByParam="*" %] |
| 異步加載提升響應 | PageAsyncTask / async/await | public async Task BindPostsAsync() |
| 前端模板引擎 | Knockout/Vue/React + WebAPI | 分離前後端,Repeater 僅輸出 JSON |
| 控件 | HTML 控制度 | 內置功能 | 性能 | 推薦場景 |
|---|---|---|---|---|
| Repeater | 完全控制 (無外層 table) | 無 (純模板) | 最輕量、最快 | 自定義佈局、博客列表、產品展示 |
| GridView | 輸出 table,難定制 | 分頁、排序、編輯、選擇 | 較重 | 後台管理、表格數據、快速原型 |
| ListView | 完全控制 | 分頁、排序、編輯、分組 | 中等 | 需要分頁/編輯的列表頁 |
public class PostRepository {
private readonly string _connStr;
public PostRepository(string connStr) { _connStr = connStr; }
public IEnumerable<Post> GetPosts(int page, int pageSize) {
var posts = new List<Post>();
string sql = @"SELECT Title, Author, PublishTime, Summary
FROM Posts ORDER BY PublishTime DESC
OFFSET @offset ROWS FETCH NEXT @pageSize ROWS ONLY"; // SQL Server 2012+
using (var conn = new SqlConnection(_connStr))
using (var cmd = new SqlCommand(sql, conn)) {
cmd.Parameters.AddWithValue("@offset", (page - 1) * pageSize);
cmd.Parameters.AddWithValue("@pageSize", pageSize);
conn.Open();
using (var reader = cmd.ExecuteReader()) {
while (reader.Read()) {
posts.Add(new Post {
Title = reader.GetString(0),
Author = reader.GetString(1),
PublishTime = reader.GetDateTime(2),
Summary = reader.GetString(3)
});
}
}
}
return posts;
}
}
將靜態 HTML 片段提取為 Repeater 的 ItemTemplate,後台通過 ADO.NET 查詢數據綁定,是從靜態頁遷移到動態數據驅動的最輕量、可控方案。保留 HTML 結構不變,僅在動態數據點插入 <%# Eval("Field") %> 表達式,實現零重寫遷移。