摘要:[ASP.NET] 解決在 User Control 中使用 Bundling 發生重複輸出 Script 或 Style 問題
前言
當在 ASP.NET Web Form 網站中使用了 ASP.NET Bundling 套件時,又碰到使用 User Control 時在該 User Control 內有綁定專屬的 Script 且此 User Control 會在同頁面上放置 1 個以上的情況,就會發生網頁畫面輸出後重複輸出了相同 Script 的問題,本篇來說明解決方法。
問題情境範例
如 Bundling Config 設定如下。
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/base")
.Include("~/Scripts/jquery-1.9.1.js",
"~/Scripts/v3.1.0/bootstrap.js"));
bundles.Add(new ScriptBundle("~/bundles/base-plugin")
.Include("~/Scripts/datepicker/bootstrap-datepicker.min.js"));
}
}
如網頁內容如下並拉入了 3 個相同的 User Control。
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Sample.aspx.cs" Inherits="Sample" %>
<%@ Register Src="~/Module/ucDateTime.ascx" TagPrefix="uc1" TagName="ucDateTime" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<%: Scripts.Render("~/bundles/base") %>
</head>
<body>
<form id="form1" runat="server">
<div>
<uc1:ucDateTime runat="server" ID="ucDateTime" />
<uc1:ucDateTime runat="server" ID="ucDateTime1" />
<uc1:ucDateTime runat="server" ID="ucDateTime2" />
</div>
</form>
</body>
</html>
如 User Control 內容如下,在 User Control 內綑綁了 Script
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="ucDateTime.ascx.cs" Inherits="Module_ucDateTime" %>
<%: Scripts.Render("~/bundles/base-plugin") %>
<div class="input-group">
<asp:TextBox ID="txtDateTime" runat="server" class="form-control date-picker input-mask-date" data-date-format="yyyy-mm-dd"></asp:TextBox>
<span class="input-group-addon">
<i class="icon-calendar bigger-110"></i>
</span>
</div>
當網頁執行時就會重複輸出綑綁的 Script,如下圖紅框所示。
解決方法
如以上範例所示,當發生這種問題時第一種解法就是將 plugin 並到 base 綑綁中,但是當網站某些頁面不需要使用到此 plugin 時,這些 plugin 就變成多餘的載入,所以為了要更有彈性的在適當的頁面載入且不要重複載入,我們可以將原本在 Bundling Config 就 Include 的動作更換到 User Control 中去處理。
移除在 User Control 頁面上的 Scripts.Render() 標籤,接著在 User Control 的 Code Behind 中動態 Include 其專屬的 plugin 虛擬路徑,先透過 GetBundleFor(bundleVirtualPath) 方法取得在 Bundling Config 中設定的 "~/bundles/base" 路徑綑綁的集合,再動態的 Include 其 plugin 路徑進去,如下程式碼。
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
BundleTable.Bundles
.GetBundleFor("~/bundles/base")
.Include("~/Scripts/datepicker/bootstrap-datepicker.min.js");
}
另外註明一點,Bundling 如 Include 了相同路徑將會排除掉相同的路徑,所以最後還是只會有一個路徑存在於集合中,最後在執行一次測試。
參考資料
BundleCollection.GetBundleFor 方法
以上文章敘述如有錯誤及觀念不正確,請不吝嗇指教
如有侵權內容也請您與我反應~謝謝您 :)