.NET TIPS

[ASP.NET]アプリケーションにログ参照のユーティリティを追加するには?

山田 祥寛
2004/03/12

 別稿「TIPS:[ASP.NET]ASP.NETアプリケーションに独自の拡張子を追加するには?」では、ある特定の「拡張子」に対してカスタムのハンドラ・クラスをマッピングする方法を紹介した。しかし、構成ファイルの設定を変更することで、特定の「拡張子」だけでなく、特定の「ファイル名」に対してもカスタムのハンドラ・クラスをマッピングできる。

 アプリケーションのトレース情報を参照するユーティリティ「trace.axd」などは、「ファイル名」にカスタムのハンドラ・クラスをマッピングした格好の例である。アプリケーション配下にtrace.axdというファイルが存在しないのに、そのファイル名を指定すると該当するアプリケーションのトレース情報が表示されることを不思議に思ったことがあるかもしれない。

trace.axdの実行結果
trace.axdという実ファイルが存在するわけではないが、このファイルにアクセスすると、アプリケーション共通のトレース情報が表示される(この機能を使用するには、web.configファイルで<trace>属性を設定している必要がある)。

 しかし、これも裏ではHTTPハンドラ・クラスが動作していることを理解していれば、不思議でも何でもない。内部的には、trace.axdというリクエストに対して、machine.configで紐付けられたTraceHandlerというクラスが動作しているに過ぎないのだ(このクラスはリファレンス・マニュアルには掲載されていない)。このように、ASP.NETではHTTPハンドラ・クラスを利用することで、アプリケーション共通のユーティリティ機能を設置することもできる。

 本稿では、これを利用してログ参照ユーティリティ「LogAccess.Util」を作成してみることにしよう。LogAccess.Utilは、アプリケーション配下の任意のフォルダ上で使用することができ、アクセスしたフォルダ配下(サブフォルダを含む)に属する全ファイルのログ情報を一覧表示するものとする。なお、ログ情報としては、別稿「TIPS:[ASP.NET]アプリケーション共通のロギングを行うには?(Global.asax編)」や「同(HTTPモジュール編)」で収集したaccessLogテーブルのデータを利用する。

 このユーティリティにアクセスすると、ログ情報を次のような画面で表示できる。

ログ参照ユーティリティ「LogAccess.Util」の完成画面
「http://localhost/netIns/」配下のファイルに関するログ情報を表示する。

 HTTPハンドラ・クラスとなるログ参照ユーティリティ「LogAccess.Util」のソース・コードは以下のとおり。

using System;
using System.IO;
using System.Web;
using System.Data;
using System.Data.SqlClient;

namespace Com.Msn.Wings {
  public class LogAccessHandler : IHttpHandler {
    public bool IsReusable {
      get {
        return true;
      }
    }
    public void ProcessRequest(HttpContext context) {
      String strTmp = context.Request.Url.ToString();
      String strPth = strTmp.Substring(0, strTmp.LastIndexOf("/"));
      // リクエストURLから親フォルダまでのパスを取得
      SqlConnection objDb = new SqlConnection("Data Source=(local);User ID=sa;Password=sa;Persist Security Info=True;Initial Catalog=nettips");
      SqlCommand objCom = new SqlCommand("SELECT url,SUM(cnt) FROM accessLog WHERE url LIKE @url GROUP BY url",objDb);
      objCom.Parameters.Add("@url", strPth + "%");
      // 指定されたフォルダ配下のファイルに関するログ情報を取得
      objDb.Open();
      SqlDataReader objDr = objCom.ExecuteReader();
      HttpResponse res = context.Response;
      res.Write("<html>");
      res.Write("<head><title>" + strPth + "</title></head>");
      res.Write("<body>");
      res.Write("<h1>「" + strPth + "」アクセスログ</h1>");
      res.Write("<table border='1'>");
      res.Write("<tr bgcolor='Tan'><th>URL</th><th>カウント数</th></tr>");
      String color;
      int cnt = 0;
      while (objDr.Read()) {
        if (cnt % 2 == 0) {
          color = "LightGoldenrodYellow";
        } else {
          color = "PaleGoldenrod";
        }
        // 偶数行・奇数行で背景色を切り替え
        cnt++;
        res.Write("<tr bgcolor='" + color + "'>");
        res.Write("<td>" + objDr.GetString(0) + "</td>");
        res.Write("<td align='right'>" + objDr.GetInt32(1) + "</td></tr>");
      }
      res.Write("</table></body></html>");
      // 取得したログ情報をテーブル表示
      objDr.Close();
      objDb.Close();
    }
  }
}
ログ参照を行うHTTPハンドラ・クラス(C#:LogAccessHandler.cs)
 
Imports System
Imports System.IO
Imports System.Web
Imports System.Data
Imports System.Data.SqlClient

Namespace Com.Msn.Wings
  Public Class LogAccessHandler : Implements IHttpHandler
    Public ReadOnly Property IsReusable As Boolean Implements IHttpHandler.IsReusable
      Get
        Return True
      End Get
    End Property
    Sub ProcessRequest(context As HttpContext) Implements IHttpHandler.ProcessRequest
      Dim strTmp As String=context.Request.Url.ToString()
      Dim strPth As String=strTmp.Substring(0,strTmp.LastIndexOf("/"))
      ' リクエストURLから親フォルダまでのパスを取得
      Dim objDb As New SqlConnection("Data Source=(local);User ID=sa;Password=sa;Persist Security Info=True;Initial Catalog=nettips")
      Dim objCom As New SqlCommand("SELECT url,SUM(cnt) FROM accessLog WHERE url LIKE @url GROUP BY url",objDb)
      objCom.Parameters.Add("@url",strPth & "%")
      ' 指定されたフォルダ配下のファイルに関するログ情報を取得
      objDb.Open()
      Dim objDr As SqlDataReader =objCom.ExecuteReader()
      With context.Response
        .Write("<html>")
        .Write("<head><title>" & strPth & "</title></head>")
        .Write("<body>")
        .Write("<h1>「" & strPth & "」アクセスログ</h1>")
        .Write("<table border='1'>")
        .Write("<tr bgcolor='Tan'><th>URL</th><th>カウント数</th></tr>")
        Dim color As String
        Dim cnt As Integer=0
        Do While objDr.Read()
          If cnt Mod 2=0 Then
            color="LightGoldenrodYellow"
          Else
            color="PaleGoldenrod"
          End If
          ' 偶数行・奇数行で背景色を切り替え
          cnt=cnt+1
          .Write("<tr bgcolor='" & color & "'>")
          .Write("<td>" & objDr.GetString(0) & "</td>")
          .Write("<td align='right'>" & objDr.GetInt32(1) & "</td></tr>")
        Loop
        .Write("</table></body></html>")
      End With
      ' 取得したログ情報をテーブル表示
      objDr.Close()
      objDb.Close()
    End Sub
  End Class
End Namespace
ログ参照を行うHTTPハンドラ・クラス(VB.NET:LogAccessHandler.vb)

 HTTPハンドラ・クラスは、使用に先立ってコマンドラインからコンパイルを行う必要がある。コンパイルの構文は以下のとおり。

>csc /t:library /r:System.dll /r:System.Web.dll /r:System.Data.dll LogAccessHandler.cs
C#の場合のコンパイル方法
 
>vbc /t:library /r:System.dll /r:System.Web.dll /r:System.Data.dll LogAccessHandler.vb
VB.NETの場合のコンパイル方法

 以上のようにして作成したHTTPハンドラ・クラスを構成ファイルに登録するには、web.configに次のような記述の追加が必要になる。

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
  <system.web>
    <httpHandlers>
      <add verb="GET,HEAD" path="LogAccess.Util" type=
"Com.Msn.Wings.LogAccessHandler,LogAccessHandler" />

      <!--LogAccess.Utilによって、LogAccessHandlerを呼び出し-->
    </httpHandlers>
  </system.web>
</configuration>
HTTPハンドラ・クラスの登録を追加したweb.config

 HTTPハンドラ・クラスを定義するための要件、拡張子「.Util」のIISへの登録、構成ファイルの各要素・属性の意味については、別稿「TIPS:[ASP.NET].htmlや.pdfファイルをフォーム認証やロギングの対象にするには?」を参考にしてほしい。ここでは、<add>要素のpath属性には、ワイルドカードを含む拡張子の指定だけではなく、固定のファイル名も指定できるということを押さえておけばよいだろう。

 このように、HTTPハンドラ・クラスを利用することで、アプリケーション配下の不特定多数のフォルダやファイルに対する汎用的なサービスを柔軟に配置することができる。フォルダ構造には依存しないので、ほかのアプリケーションへの移植も比較的容易であるし、これをmachine.configに登録することでマシン単位のサービスとして追加できるのも魅力的だ。なお、マシン単位の配置方法については、またあらためて別稿にて紹介することとする。End of Article

カテゴリ:Webフォーム 処理対象:ログ
関連TIPS:[ASP.NET]ASP.NETアプリケーションに独自の拡張子を追加するには?
関連TIPS:[ASP.NET]アプリケーション共通のロギングを行うには?(Global.asax編)
関連TIPS:[ASP.NET]アプリケーション共通のロギングを行うには?(HTTPモジュール編)
関連TIPS:[ASP.NET].htmlや.pdfファイルをフォーム認証やロギングの対象にするには?
 
この記事と関連性の高い別の.NET TIPS
[ASP.NET]特定の拡張子に対するアクセスを制限するには?
[ASP.NET]ASP.NETアプリケーションに独自の拡張子を追加するには?
[ASP.NET]ユーザーから入力されたデータを任意のあて先にメールするには?
[ASP.NET]動的にJPEG画像を作成するには?
[ASP.NET]特定のサービスを無効にするには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間