|
.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に登録することでマシン単位のサービスとして追加できるのも魅力的だ。なお、マシン単位の配置方法については、またあらためて別稿にて紹介することとする。
|
generated by
|
|
Insider.NET 記事ランキング
本日
月間