ASP.NET ベースの Web アプリケーションにおけるパスの設定において、サーバーコントロールではないページの要素(img など)で、ルート演算子 (~) が使えない場合のパスの設定方法について書きます。
標準的なパスの設定方法については、MSDN ライブラリの ASP.NET Web サイトのパス に詳しく書いてあります。
そのページに書いてあるように、~ 演算子を使用すると、アプリケーション間での移植や、同一アプリケーション内でもページを別のフォルダーへ移動する場合、リンクや相対パスの維持が容易になります。
だたし、~ 演算子はサーバーコントロールにしか使用できません。しかしながら、img などのサーバーコントロールではない要素でも ~ 演算子を使用する、もしくは、それに代わる方法があります。
-
runat="server" 属性を追加してサーバーコントロールにしてしまう。
-
VirtualPathUtility.ToAbsolute メソッド を利用して絶対パスに変換する。
前者は簡単で、<img runat="server" src="~/Images/sample.jpg" ... のようにして ~ 演算子を使うことができます。
後者は、VirtualPathUtility.ToAbsolute メソッドを利用して ~ に相当するパスを取得する方法です。例えば、アプリケーションのエイリアスが MsdnTest の場合、引数に "~" を設定すると戻り値は "/MsdnTest" になります。
VirtualPathUtility.ToAbsolute メソッドを利用した方法を汎用的に使えるようにするには、以下のようにするのが良いと思います。
まず変換したい仮想パスを、以下のように web.config ファイルの appSettings 要素に設定します。下のケースでは、例えばアプリケーションのエイリアスが MsdnTest の場合、"/MsdnTest/" という文字列を取得することを考えています。
<appSettings>
<!-- value は配置に応じて適宜変更 -->
<add key="VirtualPath" value="~/"/>
</appSettings>
次に、以下のようなクラスを定義し、その RelativeWebRoot プロパティをコード表示ブロック <%= %> で html 要素の属性(例えば、img 要素なら src 属性)に設定します。
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Configuration;
namespace MyWebsite
{
public static class Utils
{
private static string _relativeWebRoot;
public static string RelativeWebRoot
{
get
{
if (_relativeWebRoot == null)
{
_relativeWebRoot =
VirtualPathUtility.ToAbsolute(
WebConfigurationManager.AppSettings["VirtualPath"]);
}
return _relativeWebRoot;
}
}
}
}
上記の 2 つの方法を使ったサンプルコードを以下に示します。加えて、参考に、VirtualPathUtility の各メソッドの使用例も含めました。上の画像が実行結果です。
ちなみに、このページは 155_VirtualPathUtilityExample.aspx という名前でアプリケーションルート直下の 100_Over フォルダにあります。アプリケーションのエイリアスは MsdnTest です。画像 image1.jpg および image2.jpg は、アプリケーションルート直下の Images フォルダにあります。
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
String path = Context.Request.FilePath;
sb.Append("FilePath = " + path + "<br />");
sb.Append("GetFileName = " +
VirtualPathUtility.GetFileName(path) +
"<br />");
sb.Append("GetExtension = " +
VirtualPathUtility.GetExtension(path) +
"<br />");
sb.Append("GetDirectory = " +
VirtualPathUtility.GetDirectory(path) +
"<br />");
sb.Append("IsAbsolute = " +
VirtualPathUtility.IsAbsolute(path).ToString() +
"<br />");
sb.Append("IsAppRelative = " +
VirtualPathUtility.IsAppRelative(path).ToString() +
"<br />");
string toAppRelative =
VirtualPathUtility.ToAppRelative(path);
sb.Append("ToAppRelative = " + toAppRelative +
"<br />");
sb.Append("ToAbsolute = " +
VirtualPathUtility.ToAbsolute(toAppRelative) +
"<br />");
Literal1.Text += sb.ToString();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>VirtualPathUtility Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Literal ID="Literal1" runat="server">
</asp:Literal>
<img id="image1"
runat="server"
alt="イメージ1"
src="~/Images/image1.jpg" />
<img
alt="イメージ2"
src='<%=MyWebsite.Utils.RelativeWebRoot +
"Images/image2.jpg"%>' />
</div>
</form>
</body>
</html>
上記のコードから ASP.NET がレンダリングした img 要素は以下のようになります。
<img src="../Images/image1.jpg" id="image1" alt="イメージ1" />
<img
alt="イメージ2"
src='/MsdnTest/Images/image2.jpg' />