WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

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

by WebSurfer 2018年4月24日 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 2018年4月23日 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

型付 DataSet の名前に注意

by WebSurfer 2018年4月9日 14:33

Visual Stidio のデータソース構成ウィザードを使って型付 DataSet を生成するとき、その名前を DataSet とすると、System.Data.DataSet と名前が衝突して問題を起こすので要注意という話を書きます。

型付 DataSet の作成

上の画像は、ウィザードで型付 DataSet(.xsd ファイル)を生成しようとしているところですが、ファイル名がデフォルトで DataSet.xsd となるのが諸悪の根源(?)です。

デフォルトの名前が DataSet.xsd のなるのは、自分が調べた限りでは、Visual Studio Cummunity 2015 で、ASP.NET Web Forms アプリケーションを Web サイトプロジェクトとして作り、その App_Code フォルダに .xsd ファイルを生成する場合だけでした。(それ以外ではデフォルトの名前は DataSet1.xsd となります)

なので余計に気づき難いと思います。もちろんコンパイルエラーは出ませんし。

具体的にどういうことになるかと言うと、以下の通りです。

ファイル名を DataSet.xsd とすると、それから生成される型付 DataSet の名前も以下の通り DataSet となります。

/// <summary>
///Represents a strongly typed in-memory cache of data.
///</summary>
 [global::System.Serializable()]
// ・・・中略・・・
public partial class DataSet : global::System.Data.DataSet {
        
    private ProductsDataTable tableProducts;

    // ・・・中略・・・
}

そうなると、単に DataSet と宣言しただけでは型付 DataSet に定義された DataSet と見なされます。using 句に System.Data を設定しても同じです。

下の画像を見てください。上の型付 DataSet のコードの summary に設定された "Represents a strongly typed in-memory cache of data." がインテリセンスで表示されています。

インテリセンスの表示

この状態で System.Data.DataSet を使うには、上の画像の一番下の行に書いたようにしなければなりません。

自分のケースでは、上の ds を ds.ReadXml(xmlTextReader); というように使ったのですが、ds にデータを取得できない(エラーも出ない)というトラブルにハマって 1 ~ 2 時間悩みました。

今時こんなトラブルにハマるのは自分だけかもしれませんが、一応備忘録として残しておくことにします。(笑)

Tags:

.NET Framework

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  2018年10月  >>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

View posts in large calendar