[ASP.NET] 解決在 User Control 中使用 Bundling 發生重複輸出 Script 或 Style 問題

摘要:[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 方法

 

 


以上文章敘述如有錯誤及觀念不正確,請不吝嗇指教
如有侵權內容也請您與我反應~謝謝您 :)