WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

Ajax Control Toolkit スクリプト バンドル

by WebSurfer 10. June 2018 22:31

Ajax Control Toolkit は v7.x 以前では、使用する複数のスクリプトファイルをバンドルするために ToolkitScriptManager を使っていました。(ScriptManager ではなくて)

v15.1 以降では、DevExpress の記事 How to use Bundling and CDN にありますように、ScriptManager を使ってのバンドリングが可能となっています。(ちなみに、v15.1 以降 ToolkitScriptManager は提供されていません)

以下の画像の赤枠で囲った部分を見てください。これが Ajax Control Toolkit 用の複数のスクリプトファイルがバンドルされた結果です。

バンドルされたスクリプト

ASP.NET 4.5 以降で、Visual Studio Commnunity 2015 の[Web フォーム]のテンプレートを利用して作った ASP.NET Web Forms プロジェクトに、Ajax Control Toolkit を追加し、必要なスクリプトファイルを ScriptManager で統合できるようにしてみましたので、その方法や結果から分かったことを備忘録として書いておきます。

先の記事「ASP.NET 4.5 ScriptManage」に書きましたように、Microsoft Ajax、jQuery 等のスクリプトファイルが ScriptManager で統合できるようになり、[Web フォーム]のテンプレートを利用して作ったプロジェクトでは、それらが設定済みとなっています。

なので、そのプロジェクトに Ajax Control Toolkit 用のバンドル機能を追加すると、重複などの問題で修正が必要かも知れないと思っていましたが、自分が試した限りはそういうことはなかったです。

まず、NuGet で AjaxControlToolkit のパッケージをインストールします。それだけでも基本的なコントロールは動くようになりますが、ScriptManager を利用したバンドリングを可能にするためには、StaticResources パッケージも追加でインストールする必要があります。

NuGet パッケージの追加

バージョンは Ajax Control Toolkit 本体と合わせた方がよさそうです。ここでは、先にインストールした既存の Ajax Control Toolkit 本体が v17.1.1 なので、StaticResources のバージョンもそれに合わせて v17.1.1 にしました。

なお、Visual Studio で[空]のテンプレートを選択してプロジェクトを作った場合は StaticResources パッケージだけでは不足です。追加で Antlr, WebGrease などの NuGet パッケージもインストールする必要がありますが、StaticResources をインストールする際それらも自動的に追加されるはずです。

StaticResources のインストールが完了すると、以下の画像の赤枠で示したフォルダが生成され、その中に CSS ファイル、イメージ、スクリプトファイルが格納されます。

追加された CSS とスクリプト

Content/AjaxControlToolkit フォルダ下の Images フォルダには .gif, .jpg, .png などの画像ファイルが、Styles フォルダには minify してない .css ファイルと minify した .min.css ファイルの両方が格納されます。

Scripts/AjaxControlToolkit フォルダ下の Debug フォルダには minify してない .debug.js ファイルが、Release フォルダには minify した .js ファイルが格納されます。

さらに、web.config にはデフォルトで以下の設定が追加されます。

<ajaxControlToolkit 
    useStaticResources="true" 
    renderStyleLinks="false" />

DevExpress の記事 How to use Bundling and CDN の説明によるとバンドル機能をコントロールするもののようです。

あとは、DevExpress の記事 "Manual changes required" のセクションを参考に、ScriptManager に ScriptReference を追加してやればスクリプトは一番上の画像に示したようにバンドルされます。

具体的には以下の画像の赤枠で示したコードを追加してやります。

ScriptReference の追加

赤枠部分以外の ScriptManager のコードは、Visual Studio の[Web フォーム]のテンプレートを利用して作った ASP.NET Web Forms アプリのマスタページ Site.master に自動生成されたものです。

.css ファイルについても、DevExpress の記事に従って Styles.Render をページの適当な場所に追加してやれば、.css ファイルを参照する link 要素がレンダリングされます。

ただし、.css ファイルは web.config の compilation 要素で debug="false" とするか、Global.asax の Application_Start メソッドで BundleTable.EnableOptimizations を true に設定しないとバンドルされませんので注意してください。(スクリプトファイルと異なります。理由不明)

BundleTable.EnableOptimizations を true に設定する意味については Microsoft の文書 Bundling and Minification を見てください。抜粋すると "The following code (true に設定すること) enables bundling and minification and overrides any setting in the Web.config file." ということだそうです。

web.config の compilation 要素の debug 属性の true / false でどう異なるかですが、自分が検証した限りでは、

  • .css ファイル: true で minify &バンドルあり、false で minify なしでバンドルもなし。
  • スクリプトファイル: true / false の設定にかかわらず minify &バンドルあり。

・・・となりました。

スクリプトファイルの結果がちょっと解せないです。そのままでは、debug="true" にしてもスクリプトのデバッグができません。

.debug.js 版をダウンロードさせてデバッグ可能なようにするには、上の ScriptManager の設定のところで ScriptReference をコメントアウトする他なさそうです。

あと、minify&バンドルされたスクリプトファイルのサイズですが、何と 1,248,841 バイトもありました。Ajax Control Toolkit は使わないのにスクリプトをダウンロードするように設定するというのは避けた方がよさそうです。

ちなみに、.CSS ファイルの方は minify&バンドル後で 56,240 バイトでした。

最後にもう一つ、HtmlEditorEntender には AjaxControlToolkit.HtmlEditor.Sanitizer, HtmlAgilityPack が必要です。

それなしでは先の記事「Ajax Control Toolkit デモ」で述べたような意味不明のエラーが出てハマるかもしれませんのでご注意ください。

Tags: , ,

AJAX

ASP.NET 4.5 スクリプト マッピング

by WebSurfer 24. April 2018 15:58

先の記事「ASP.NET 4.5 ScriptManager」で "テンプレートで「空」を選択した場合は、最低でも jQuery, MSAjax, WebForms の 3 つの NuGet パッケージはインストールして、ScriptManager に登録し、全てのページに ScriptManager を配置するのがよさそうです" と書きました。その手順を備忘録として残しておきます。

「空」のテンプレート

まず、「空」のテンプレートというのは何かですが、上の画像のように Visual Studio で Web アプリケーションを作成する際に「空」を選択して Web Forms にチェックを入れたものです。(画像は Visual Studio Community 2015 のもの)

上の設定で作ったアプリケーションには、先の記事で書いたような ScriptManager へのスクリプトマッピング等は一切含まれず、自力で NuGet パッケージをダウンロードして必要な設定することになります。

その手順は以下の通りです。

(1) jQuery, MSAjax, WebForms の NuGet パッケージ

jQuery, MSAjax, WebForms の NuGet

Visual Studio の[ツール(T)]⇒[NuGet パッケージマネージャー(N)]⇒[ソリューションの NuGet パッケージの管理(N)...]と進んで管理画面を開き、以下の 3 つの NuGet パッケージをインストールします。(もし Bootstrap 等も必要でしたら追加してください)

  • AspNet.ScriptManager.jQuery
  • Microsoft.AspNet.ScriptManager.MsAjax
  • Microsoft.AspNet.ScriptManager.WebForms

上の画像はインストール後のもので、バージョンはこの記事を書いた時点で最新のものです。

NuGet パッケージのインストールが完了すると、下の画像の通り JavaScript ファイルが Scripts フォルダ下にインストールされます。

スクリプトファイル

その他、ASP.NET 4.5 ScriptManager Improvements in WebForms に書いてありますが、スクリプトマッピングのためのコードが PreApplicationStart メソッドに追加されるそうです。

追加されているのを目で見て確認する方法は分かりませんが、ScriptManaget に以下の設定をすれば jQuery 3.3.1 のスクリプトファイルへの参照は正しくレンダリングされるようになりますので、間違いなく追加されていると思います。

<asp:ScriptManager runat="server">
  <Scripts>
    <asp:ScriptReference Name="jquery" />
  </Scripts>
</asp:ScriptManager>

ただし、MsAjax と WebForms の方は NuGet パーッケージのインストールだけでは不足で、Web.Optimization 関係の NuGet パッケージのインストール、バンドル定義の作成とそれの登録が追加で必要になります。

(2) Web.Optimization の NuGet パッケージ

 の NuGet

上記 (1) の手順と同様に Visual Studio で NuGet パッケージの管理管理画面を開き、以下の 2 つの NuGet パッケージをインストールします。上の画像はインストール後のもので、バージョンはこの記事を書いた時点で最新のものです。

  • Microsoft.AspNet.Web.Optimization
  • Microsoft.AspNet.Web.Optimization.WebForms

これらの NuGet パッケージのインストールはバンドル定義を行うために必要です。

(3) バンドル定義と登録

「Web フォーム」のテンプレートを使って作成すると自動生成される App_Start フォルダの BundleConfig.cs のコードを参考にバンドル定義を作成します。

参考と言っても、そのままコピペして不要な部分を削除するだけですが。コードは以下のようになります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Optimization;
using System.Web.UI;

namespace WebFormsEmpty
{
  public class BundleConfig
  {
    public static void RegisterBundles(BundleCollection bundles)
    {
      bundles.Add(new ScriptBundle("~/bundles/WebFormsJs").
      Include("~/Scripts/WebForms/WebForms.js",
              "~/Scripts/WebForms/WebUIValidation.js",
              "~/Scripts/WebForms/MenuStandards.js",
              "~/Scripts/WebForms/Focus.js",
              "~/Scripts/WebForms/GridView.js",
              "~/Scripts/WebForms/DetailsView.js",
              "~/Scripts/WebForms/TreeView.js",
              "~/Scripts/WebForms/WebParts.js"));

      bundles.Add(new ScriptBundle("~/bundles/MsAjaxJs").
      Include(
      "~/Scripts/WebForms/MsAjax/MicrosoftAjax.js",
      "~/Scripts/WebForms/MsAjax/" + 
                      "MicrosoftAjaxApplicationServices.js",
      "~/Scripts/WebForms/MsAjax/MicrosoftAjaxTimer.js",
      "~/Scripts/WebForms/MsAjax/MicrosoftAjaxWebForms.js"));
    }
  }
}

上記のバンドル定義を Global.asax の Application_Start メソッドで登録します。コードは以下のようになります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using System.Web.Optimization;

namespace WebFormsEmpty
{
  public class Global : System.Web.HttpApplication
  {
    protected void Application_Start(object sender, 
                                           EventArgs e)
    {
      BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
  }
}

(4) ScriptManager への登録

「Web フォーム」のテンプレートを使って作成すると自動生成されるマスターページ Site.Master の ScriptManager のコードを参考に、クライアントにレンダリングされるスクリプトを登録します。

そのままコピペして、今回は使わない bootstrap, respond の部分を削除するだけです。コードは以下のようになります。

<asp:ScriptManager runat="server">
  <Scripts>
    <asp:ScriptReference Name="MsAjaxBundle" />
    <asp:ScriptReference Name="jquery" />
    <asp:ScriptReference Name="WebForms.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/WebForms.js" />
    <asp:ScriptReference Name="WebUIValidation.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/WebUIValidation.js" />
    <asp:ScriptReference Name="MenuStandards.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/MenuStandards.js" />
    <asp:ScriptReference Name="GridView.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/GridView.js" />
    <asp:ScriptReference Name="DetailsView.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/DetailsView.js" />
    <asp:ScriptReference Name="TreeView.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/TreeView.js" />
    <asp:ScriptReference Name="WebParts.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/WebParts.js" />
    <asp:ScriptReference Name="Focus.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/Focus.js" />
    <asp:ScriptReference Name="WebFormsBundle" />
  </Scripts>
</asp:ScriptManager>

上のコードで Assembly と Path を指定した ScriptReference がありますが、それらは ASP.NET 4.5 ScriptManager Improvements in WebForms に書いてありありますように、deduping(重複排除)のための "special arrangement"だそうです。(どのような仕組みで排除されるのかは分かりませんが)

結果、上記 (3) のバンドル定義に従ってバンドルされたスクリプト定義への参照と、jQuery 3.3.1 のスクリプトファイルへの参照が、正しい順序でクライアントにレンダリングされます。

<script src="/bundles/MsAjaxJs?v=c42ygB2...></script>
<script src="Scripts/jquery-3.3.1.js" .....></script>
<script src="/bundles/WebFormsJs?v=AAyiA...></script>

Tags: ,

ASP.NET

ASP.NET 4.5 ScriptManager

by WebSurfer 23. April 2018 16:47

ASP.NET 4.5 以降での話ですが、クライアントスクリプトを利用するサーバーコントロールが正しく機能するには、必要なクライアントスクリプトの ScriptManager への登録と、全ページでの ScriptManager の配置が必要という話を書きます。

RequiredFieldValidator

元の話は MSDN Forum のスレッド「検証コントロール + マスターページ in WebサイトのWebアプリケーション」です。

MSDN Forum の話は検証コントロールによるクライアント側での検証が働かなかったということですが、ScriptManager を正しく使わないと、多分それ以外(ASP.NET AJAX Extensions など)にも影響があると思われます。

ASP.NET 4.5 では、Microsoft Ajax と WebForms 用のスクリプトファイルはアプリケーションの Scripts フォルダに格納し、そこから ScriptManager を介してダウンロードできるように改善されたそうです。(旧来は WebResource.axd, ScriptResource.axd というハンドラを使ってサーバーコントロールのリソースからダウンロードしていました)

さらに、jQuery, Bootstrap 等のスクリプトも、Microsoft Ajax と WebForms 用のスクリプトに加えて、ScriptManager で統合できるようになりました。

そのあたりの詳しい話は MSDN Blog の記事 ASP.NET 4.5 ScriptManager Improvements in WebForms に書いてありますので一読されると良いと思います。

Visual Studio Commnunity 2015 のテンプレートを利用して ASP.NET Web フォームアプリケーションを作成すると、以下のスクリプト関係の NuGet パッケージが自動的にプロジェクトにインストールされ、App_Start/BundleConfig.cs にバンドル定義のコード、Global.asax の Application_Start メソッドにバンドル定義を登録するためのコードが自動生成されます。

NuGet パッケージ

そして、マスターページ Site.Master に ScriptManager が配置され、必要なスクリプト参照が登録されます。Visual Studio Community 2015 の場合は以下の通りとなります。

<asp:ScriptManager runat="server">
  <Scripts>
    <asp:ScriptReference Name="MsAjaxBundle" />
    <asp:ScriptReference Name="jquery" />
    <asp:ScriptReference Name="bootstrap" />
    <asp:ScriptReference Name="respond" />
    <asp:ScriptReference Name="WebForms.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/WebForms.js" />
    <asp:ScriptReference Name="WebUIValidation.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/WebUIValidation.js" />
    <asp:ScriptReference Name="MenuStandards.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/MenuStandards.js" />
    <asp:ScriptReference Name="GridView.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/GridView.js" />
    <asp:ScriptReference Name="DetailsView.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/DetailsView.js" />
    <asp:ScriptReference Name="TreeView.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/TreeView.js" />
    <asp:ScriptReference Name="WebParts.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/WebParts.js" />
    <asp:ScriptReference Name="Focus.js" 
        Assembly="System.Web" 
        Path="~/Scripts/WebForms/Focus.js" />
    <asp:ScriptReference Name="WebFormsBundle" />
  </Scripts>
</asp:ScriptManager>

この ScriptManager の新機能には重複排除の機能も含まれているようで、例えば検証コントロールを使っても、旧来だったら自動生成される WebResource.axd ハンドラを使うコードは生成されません。

テンプレートでアプリケーションを作ったら、必ず上記の <Scripts> ~ </Scripts> の間のコードを含めた ScriptManager が全ページに配置されるようにするのが正解と思われます。

単に <asp:ScriptManager runat="server"></asp:ScriptManager> としたら、検証コントロールを配置してもクライアント側での検証が動かなかったというのが上に紹介した MSDN Forum の話でした。

なお、テンプレートの選択で「Web フォーム」ではなく「空」を選んだ場合はスクリプトの設定は一切されず、例えばその状態で検証コントロールを使うと、以下のようなサーバーエラーとなります。

"WebForms UnobtrusiveValidationMode には、'jquery' の ScriptResourceMapping が必要です。jquery (大文字と小文字が区別されます) という名前の ScriptResourceMapping を追加してください。"

ASP.NET 4.5 で利用可能になった控えめな JavaScript による検証を止めて旧来のものに戻すとか(web.config の appSettings で設定可能)、クライアント側での検証を無効にすればエラーは回避できますが、それは望ましい解決法ではないので、エラーメッセージに従って対処した方がよさそうです。

また、検証コントロール以外にも、クライアントスクリプトを利用するサーバーコントロール(UpdatePanel とか)を使うと、必要なスクリプトがダウンロードされず期待通り動かないという問題が出そうな気がします。

なので、テンプレートで「空」を選択した場合は、最低でも jQuery, MSAjax, WebForms の 3 つの NuGet パッケージはインストールして、ScriptManager に登録し、全てのページに ScriptManager を配置するのがよさそうです。

その手順は別の記事「ASP.NET 4.5 スクリプトリソースマッピング」に書きましたので、興味があれば見てください。

Tags: ,

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  October 2024  >>
MoTuWeThFrSaSu
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

View posts in large calendar