none
aspx の Page ディレクティブに RequestEncoding を指定する方法 RRS feed

  • 質問

  • お世話になっております。

    asp.net (.net 4.0) で、IIS 7上で動作する web アプリケーションを制作しています。

    URL引数 (Request) に、日本語文字を指定したところ文字化けしてしまいました。

    実際にやろうとしていることは、ファイル名の検索一覧表示で、

    http://sample/default.aspx?n=ファイル

    などと指定してアクセスさせると

    For Each filePath As String In System.IO.Directory.GetFiles(dirPath, "*" & Request("n") & "*")
      Response.Write(filePath & "<br>")
    Next
    のように記載したコードを経て、URL引数の n に指定した文字を含むファイル一覧を表示させます。

    うまく検索が成功しないため、Response.Write(Request("n")) のように指定して表示させたところ、すでに文字化けしてしまいました。

    調べてみますと、入力や出力のエンコードを指定できるそうです。

    http://msdn.microsoft.com/ja-jp/library/39d1w2xf.aspx
    http://aspnet.keicode.com/aspnet/use-utf8.php

    上記の内容をもとに aspxファイルの先頭のPageディレクティブ?に RequestEncoding="utf-8" と指定してみましたところ

    「エラー 1 属性 'requestencoding' の解析中にエラーが発生しました: 型 'System.Web.UI.Page' には 'requestencoding' というパブリック プロパティは含まれていません。 \\server\default.aspx 1 」

    とエラーになってしまいまいました。

    「入力のエンコード」は存在せず、ただ文字列になるのみとの情報も見つけました。

    http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=41382&forum=7

    入力(URL変数)の基本のエンコードはどこで設定されるのでしょうか?もしくはエンコード自体無く、.net内部にニュートラルな文字列として格納されるのでしょうか?

    本来は2バイト文字列をURL引数に指定することは良くないとは承知していますが、URL手打ちで指定させたいため、2バイト文字指定も原則許容したいと思っています。

    ※補足なのですが、 URL rewrite module を使用しています。 http://sample/あいうえおhttp://sample/default.aspx?n=あいうえお と変換させています。

    恐れ入りますが
    ご存知の方、ご教示のほど宜しくお願い致します。




    2013年11月25日 14:46

回答

すべての返信

  • 以下のページのような話ではないのですか?

    ブラウザによる URL のエンコーディング
    http://surferonwww.info/BlogEngine/post/2011/11/07/Encoding-of-URL-directly-written-in-address-bar-of-browser.aspx

    であれば、解決策は URL の文字列を URL エンコーディングするということになります。

    • 回答としてマーク Always fresh 2013年11月26日 0:44
    • 回答としてマークされていない Always fresh 2013年11月26日 1:48
    2013年11月25日 16:09
  • すでに解決済みのマークがついてしまっていますが・・・

    > URL rewrite module を使用しています。 http://sample/あいうえお
    > を http://sample/default.aspx?n=あいうえお と変換させています。

    上記のところを見落としてました。

    URL rewrite module の中身が分からないのでハズレかもしれませんが、以下のような問題と同じではないのでしょうか?

    日本語の著者名の問題
    http://surferonwww.info/BlogEngine2/post/2011/06/13/Problem-on-Japanese-author-name.aspx

    つまり、URL rewrite module が "http://sample/あいうえお" を "http://sample/default.aspx?n=あいうえお" に書き換える際の "あいうえお" のエンコーディングに問題があるのでは?

    そうであれば、解決策は URL rewrite module を修正するということになると思うのですが。

    • 回答としてマーク Always fresh 2013年11月26日 2:16
    2013年11月26日 1:40
  • SurferOnWww様

    どうも有難う御座います。

    第二階層の文字列をクエリ文字列nに代入するよう URL rewrite moduleに記載して
    ([正規表現入力パターン] dir/(.+)$ [書き換えURL] dir/default.aspx?n={R:1})
    "http://server/dir/あ" と直打ちクエリを発行し、
    aspx側のPage_Loadイベントで、RequestヘッダをSaveAsメソッドで吐き出させてみたところ、仰る通り

     GET /dir/default.aspx?n=縺・  HTTP/1.1
     ...
     X-Original-URL: /dir/%E3%81%82

    と、aspxへ渡ってくる際に文字デコードが自動でなされてしまっておりました。

    URL rewrite module で、文字デコードをさせない記載方法を知り、書き換えURLを dir/default.aspx?n={UrlEncode:{R:1}} とすることで、aspxへ渡ってきた内容が

     GET /dir/default.aspx?n=%E3%81%82 HTTP/1.1
     ...
     X-Original-URL: /dir/%E3%81%82

    と、エンコードされたままになることを確認できました。

    しかしながら、この状況においても Response.Write(Request("n")) などとコードを書くと

     縺・

    と表示されてしまいました。

    どうやら、SHIFT_JISでエンコードされたと解釈しているようで、

     Response.Write(System.Text.Encoding.UTF8.GetString(System.Text.Encoding.GetEncoding("SHIFT_JIS").GetBytes(Request("n"))))

     と、SHIFT_JISからUTF-8へ戻す(出力ページがUTF-8エンコードであるため)コードを書いてみましたところ

     あ

     と無事表示されました。IISや.NETの環境設定やOS環境に依存するのかもしれません。本番運用までに調べてみようと思います。

    Fiddler ツール、およびご掲載されている記事、とても参考になります。






    2013年11月26日 2:02
  • > しかしながら、この状況においても Response.Write(Request("n")) などとコードを書くと

    普通、クエリ文字列を取得するには、HttpRequest.QueryString プロパティを使って、以下のようにするのですが(注: C# の書き方です)・・・

    Request.QueryString["n"]

    これが原因ではないかもしれませんが(検証してませんので)、気になった点をとりあえず連絡します。

    2013年11月26日 2:28
  • SurferOnWww 様

    どうも有難う御座います。 Request.QueryString() と記載してアクセスするように癖をつけたいと思います。

    先ほどの SHIFT_JIS から UTF-8 へ変換をかける方法ですが、いくつかの文字列で失敗してしまいました(例として、"拒"を指定すると URLには %E6%8B%92 とエンコードされるのですが、 System.Text.Encoding.GetEncoding("SHIFT_JIS").GetBytes(Request.QueryString("n"))) をかけると、4バイト(E6 8B 92 45) と変換されてしまいました)。

    web.config の System.Web に Globalization 要素で requestEncoding="UTF-8"と明示して UTF-8 で取得させるようにして、なんとか安定して日本語のクエリ文字列を得られるようになりました。URL rewrite module で UrlEncode 文字列関数を指定しなかった場合の自動変換も、web.config による指定によって、UTF-8として日本語に変換されました(GET /dir/default.aspx?n=あ ... X-Original-URL: /dir/%E3%81%82)。

    検証はまだ完全ではありませんが、web.config で requestEncoding="UTF-8" を明示することで、手打ちで日本語文字列を指定する目的を一応達成させることが出来たようです。ご教示いただいた記事に掲載されておられます、URL のクエリ文字列以前(左側)がブラウザから軒並みUTF-8で送られてくるところがミソですね。


    • 編集済み Always fresh 2013年11月26日 3:15 誤記修正
    2013年11月26日 3:14
  • Url Rewrite Module が絡んで不可解な状況になっているようですね。


    > 先ほどの SHIFT_JIS から UTF-8 へ変換をかける方法ですが、いくつかの文字列で失敗して
    > しまいました(例として、"拒"を指定すると URLには %E6%8B%92 とエンコードされるのですが、

    ブラウザから直接、

    GET /dir/default.aspx?n=%E6%8B%92 HTTP/1.1

    という要求が出れば、サーバーで Request.QueryString("n") は間違いなく "拒" になるはずなのですが・・・


    default.aspx のコードの適当なところにブレークポイントを設定してデバッガで QueryString を見てはいかがですか? QueryString のところにマウスのカーソルを当てれば "拒" なら以下のようになっているはずです。(62d2 は UTF-16 での "拒" です)

    Request.QueryString = {n=%u62d2}


    > System.Text.Encoding.GetEncoding("SHIFT_JIS").GetBytes(Request.QueryString("n")))
    > をかけると、4バイト(E6 8B 92 45) と変換されてしまいました)。

    そうなるためには、Request.QueryString("n") は "拒" ではなくて、Shift_JIS で E6 8B 92 45 相当の文字列すなわち "諡脱" になるのですが・・・

    UTF-8 で E6 8B 92 45 相当の文字列は "拒E" なのですが、何故か Request.QueryString("n") で得られる文字列の Shift_JIS バイト列と一部一致してます。このあたりも一体何が起こっているのか不可解です。


    > web.config の System.Web に Globalization 要素で requestEncoding="UTF-8"と明示して
    > UTF-8 で取得させるようにして、なんとか安定して日本語のクエリ文字列を得られるように
    > なりました。

    ここのところも不可解です。

    requestEncoding はデフォルトで UTF-8 です(machine.config に設定があるはずです)。

    また、requestEncoding の設定は、サーバーによる POST データのエンコーディングの解釈には影響がありますが、GET 要求 URL と一緒に送るクエリ文字列の解釈には影響ないはずなのですが・・・


    とにかく、まずデバッガを使って、default.aspx のコードの Request や QueryString の中身を見て、どこでどう期待と違っているか調べてはいかがでしょう。

    それで分からない場合は、Url Rewrite Module のソースコードまで追いかける必要があると思います。

    2013年11月26日 6:09
  • お使いの Url Rewrite Module というのは IIS7.x 用に Microsoft が提供しているもの、即ち以下のページで紹介されているものだと思いますが、それを使って質問者さんと同様な設定にして検証してみました。

    Tip/Trick:URL書き換え拡張の使用による一般的なSEO問題の修正
    http://www.atmarkit.co.jp/fdotnet/scottgublog/20100430urlrewrite/urlrewrite.html

    結果、質問者さんが書かれているような問題は全くなかったです。

    開発環境は Vista Ultimate SP2 32-bit, IIS7(アプリケーションプールは ASP.NET v4.0 で統合パイプラインモード), ASP.NET 4, requestEncoding は未設定(デフォルトで UTF-8)で、使用したブラウザは IE9 です。

    同じ Url Rewrite Module をお使いだとすると、どこかのファイルが壊れているとか、質問者さん固有の問題かもしれません。


    検証結果詳細を以下に書いておきます。

    書き換えルール
    --------------
    <rewrite>
        <rules>
            <rule name="Japanese Query String Test">
                <match url="dir/(.+)$" />
                <action type="Rewrite" url="0024-QueryString.aspx?n={R:1}" />
            </rule>
        </rules>
    </rewrite>

    IE9 のアドレスバーに直打ちした URL
    ----------------------------------
    http://aspnet4site/dir/

    Fiddler2 による上記要求のキャプチャ結果
    ---------------------------------------
    GET http://aspnet4site/dir/%E3%81%82 HTTP/1.1
    Accept: text/html, application/xhtml+xml, */*
    Accept-Language: ja-JP,en-US;q=0.7,fr-FR;q=0.3
    User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0)
    Accept-Encoding: gzip, deflate
    Connection: Keep-Alive
    Host: aspnet4site
    Cookie: ASP.NET_SessionId=4z1ylkfmck32f2qgoo4tt4b3

    IE9 に表示された応答
    --------------------
    X-Original-URL: /dir/%E3%81%82
    あ[E3][81][82]
     
    Request.Url.ToString(): http://aspnet4site/0024-QueryString.aspx?n=あ
    Request.RawUrl: /dir/あ
    Request.QueryString["n"]: あ

    検証に使った 0024-QueryString.aspx のソース
    -------------------------------------------

    <%@ 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)
        {
            NameValueCollection headers = Request.Headers;
            string[] keys = headers.AllKeys;
            for (int i = 0; i < keys.Length; i++)
            {
                if (keys[i] == "X-Original-URL")
                {
                    string[] values = headers.GetValues(keys[i]);
                    Response.Write("X-Original-URL: " + Server.HtmlEncode(values[0]) + "<br />");
                }
            }
            
            string s = Request.QueryString["n"];        
            if (s != null)
            {
                Response.Write(s);
                byte[] b = System.Text.Encoding.UTF8.GetBytes(s);
                for (int i = 0; i < b.Length; i++)
                {
                    Response.Write(string.Format("[{0:X2}]", b[i]));
                }
            }
    
            Label1.Text = "Request.Url.ToString(): " + Request.Url.ToString();
            Label2.Text = "Request.RawUrl: " + Request.RawUrl;
            Label3.Text = "Request.QueryString[\"n\"]: " + Request.QueryString["n"];        
        }
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Label ID="Label1" runat="server"></asp:Label>
            <br />
            <asp:Label ID="Label2" runat="server"></asp:Label>
            <br />
            <asp:Label ID="Label3" runat="server"></asp:Label>
        </div>
        </form>
    </body>
    </html>


    • 編集済み SurferOnWww 2013年11月28日 8:01 誤字訂正
    2013年11月28日 8:00
  • SurferOnWww様

    検証までおこなっていただき、大変恐れ入ります。

    お粗末ながら、原因が判明しました。

    IIS7 マネージャーで、サイトのルート階層での ".NET グローバリゼーション" 設定を確認してみたところ
    エンコードに関する「ファイル」「要求」「応答」の設定が "shift_jis" となっており、
    ルート階層の web.config を確認したところ
     <globalization requestEncoding="shift-jis" responseEncoding="shift-jis" />
    の行を発見しました。

    「応答」と「要求」について、utf-8(既定)に適用させたところ、まったく同じ結果を得られました。

    他のアプリケーションに影響がないことを確認してサイト全体を既定のエンコーディング設定で動作させるようにするか、URL rewrite module を使用する階層へ忘れずにutf-8エンコーディング設定をかけるようにしたいと思います。

    お手をわずらわせてしまい申し訳ありませんでした。
    どうも有難う御座いました。


    2013年11月28日 9:56