傳統多版本網站(如中/英/日文)常面臨維護困境。本文提出「單一容器頁面 + HttpHandlerFactory 攔截 + XML 映射」架構,實現零程式碼擴充多版本頁面。
.aspx 請求,若實體頁面不存在則導向唯一容器頁 WebForm2.aspxAddParsedSubObject 事件中,依請求 URL 從 XML 讀取對應用戶控件路徑MasterPageControl(繼承 HtmlContainerControl)動態 LoadControl 載入用戶控件public class WebPageHandlerFactory : IHttpHandlerFactory
{
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string path)
{
if (IsExistedPage(path))
return PageParser.GetCompiledPageInstance(url, path, context);
if (!path.ToLower().EndsWith(".aspx"))
path = Path.Combine(path, "webform2.aspx");
url = ReplaceUrl(url);
path = ReplaceUrl(path);
return PageParser.GetCompiledPageInstance(url, path, context);
}
private bool IsExistedPage(string path) => path.ToLower().IndexOf("webform2.aspx") > 0;
private string ReplaceUrl(string input)
{
return new Regex(@"\w+\.aspx").Replace(input, "webform2.aspx");
}
public void ReleaseHandler(IHttpHandler handler) { }
}
web.config 註冊:
<httpHandlers>
<add verb="*" path="/*.aspx" type="WebApplication_Test.WebPageHandlerFactory, WebApplication_Test"/>
</httpHandlers>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="WebApplication_Test.WebForm2" %>
<%@ Register TagPrefix="ccWebUI" Namespace="Common.UI" Assembly="Common.UI" %>
<ccWebUI:MasterPageControl id="MPContainer" runat="server"></ccWebUI:MasterPageControl>
public partial class WebForm2 : BasePage
{
protected override void AddParsedSubObject(object obj)
{
base.AddParsedSubObject(obj);
if (obj is MasterPageControl)
{
var config = new AppSettingPage(Context);
if (!string.IsNullOrEmpty(config.TeamplateFilePath))
{
((MasterPageControl)obj).Controls.Clear();
((MasterPageControl)obj).TemplateFile = config.TeamplateFilePath;
}
}
}
}
AppSettingPage 解析請求 URL,配合 TemplateConfig.xml 回傳控件路徑:
public class AppSettingPage
{
public string TeamplateFilePath { get; private set; }
public AppSettingPage(HttpContext context) { AnalysisUrl(context.Request.Url.ToString().ToLower()); }
private void AnalysisUrl(string url)
{
foreach (var page in TemplateConfig.Pages())
if (Regex.IsMatch(url, page.pattern, RegexOptions.IgnoreCase))
{ TeamplateFilePath = page.target_page; break; }
}
}
TemplateConfig.xml:
<pages>
<page pageName="index.aspx" target-page="index.ascx"/>
<page pageName="index2.aspx" target-page="index2.ascx"/>
</pages>
多版本新聞頁範例:
<pages>
<page pageName="中文新聞.aspx" target-page="中文新聞控件.ascx"/>
<page pageName="英文新聞.aspx" target-page="英文新聞控件.ascx"/>
<page pageName="日文新聞.aspx" target-page="日文新聞控件.ascx"/>
</pages>
BasePage:覆寫 Render 輸出完整 HTML 骨架MasterPageControl:OnInit 呼叫 BuildMasterPage 載入用戶控件,隱藏自身標籤輸出此架構將頁面邏輯與控件載入完全解耦,新增版本僅需新增 .ascx 與 XML 設定,無須修改任何 C# 程式碼,極大降低維護成本。