none
MVC ルーティングでピリオド(.)が使えない RRS feed

  • 質問

  • RouteCollectionExtensions.MapRouteでrouteTemplate: "/Home/{id}/{id2}.xxx"を設定して

    /Home/Action/1.xxx でアクセスすると

    HTTP エラー 404.0 - Not Found

    となります

    routeTemplate: "Home/{id}/{*id2}"を設定しても

    HTTP エラー 404.0 - Not Found

    となります

    routeTemplate: "/Home/{id}/{id2}-xxx"を設定して

    /Home/Action/1-xxx でアクセスすると正常に動作するので基本的な書き方は間違ってないと思っています。

    区切り文字としてピリオド(.)は使えないのですか?それとも何かの設定が必要なのですか?

    Visual Studio 2013 / MVC5 

    • 編集済み naki02 2015年3月21日 14:43
    2015年3月21日 14:33

すべての返信

  • 何故そんなことがしたいのかお聞かせいただけると嬉しいのですが・・・
    2015年3月21日 15:18
  • ブラウザというかクライアント側でテキストファイルや画像ファイルなど拡張子別に動作するのに対応させたいためです
    2015年3月21日 21:32
  • 大きなところで代表例を挙げるとすればGoogle Photos (旧Picasa)の画像URLはこんな感じになってます。

     http://lh5.googleusercontent.com/-XHnZnd7Fjlk/T_CBV14AR6I/AAAAAAAAAYY/JN5_6ryjkeE/w1280-h1024/abc.jpg

    w1280-h1024の部分は様々なオプションを指定することが出来、元の画像に対してリサイズや回転など加工して画像を返します。

    abc.jpgのファイル名の部分は元の画像には関係なくなんでも指定出来ます。

    こんなことを再現するにはどうすればいいかなと思っておりました。
    2015年3月21日 22:08
  • 依然として質問者さんのやりたいことが理解できていませんが・・・

    > 区切り文字としてピリオド(.)は使えないのですか?

    その質問に対する答なら「使える」です。

    どうして質問者さんのケースで 404 Not Found になるのかと言うと、想像ですが、url パターンが一致しないからだと思います。

    • 編集済み SurferOnWww 2015年3月22日 3:33 一部訂正
    2015年3月22日 3:32
  • ピリオドが使えると言っておいて使えないと何なので、実際に検証して見ました。

    環境は、Vista SP2, Visual Studio 2010 Professional の MVC4 インターネットアプリケーションテンプレートで作ったアプリを、ASP.NET 開発サーバー上で動かしています。

    質問者さんのやりたいことがはっきり分かっていませんが、例えば、ブラウザから、

    http://<hostname>/Home/Action/1200x800/sample.jpg

    と要求を出した時に、Home コントローラーの Action アクションメソッドを呼び出して、そのメソッドの引数に "1200x800" と "sample" という文字列を渡すということと想像して検証してみました。

    まずルーティング定義の追加。質問者さんのやり方は自分には意味不明ですので、普通に、テンプレートでアプリを作った時に自動生成される RouteConfig クラスに、以下のように追加します。

    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            // ・・・中略・・・
    
            // 以下を追加
            routes.MapRoute(
                name: "Resize",
                url: "{controller}/{action}/{size}/{filename}.jpg"
            );
        }
    }

    コントローラーとアクションメソッドの定義。

    public class HomeController : Controller
    {
        // ・・・中略・・・
    
        // Action アクションメソッドの定義。
        public ActionResult Action(string size, string filename)
        {
            ViewBag.Message = "(サイズ: " + size + 
                " / ファイル名: " + filename + ".jpg)";
    
            return View();
        }
    }

    ビューの定義。

    @{
        ViewBag.Title = "画像のリサイズ。";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    
    <hgroup class="title">
        <h1>@ViewBag.Title</h1>
        <h2>@ViewBag.Message</h2>
    </hgroup>
    
    <article>
        <p>
            この領域を使用して追加の情報を提供します。
        </p>
    </article>
    
    <aside>
        <h3>挿入タイトル</h3>
        <p>
            この領域を使用して追加の情報を提供します。
        </p>
    </aside>

    /Home/Action/1200x800/sample.jpg という要求で <h2>@ViewBag.Message</h2> のところに "(サイズ: 1200x800 / ファイル名: sample.jpg)" と表示されます。

    ちなみに、url のパターンを間違える(例えば sample.jpg でなく sample としたような場合)は 404 Not Found エラーになります。



    • 編集済み SurferOnWww 2015年3月22日 4:18 表示の崩れ訂正
    2015年3月22日 4:06
  • APIではなくRouteConfigで教えていただいたもので試したがうまくいきませんでした。最初の投稿と同じ内容になってしまいますが

    url: "{controller}/{action}/{size}/{filename}.jpg"

    http://localhost:50970/Home/Action/1200x800/sample.jpg

    はダメ

    url: "{controller}/{action}/{size}/{filename}-jpg"

    http://localhost:50970/Home/Action/1200x800/sample-jpg

    はOK

    コードとかじゃなくIISの設定とかなんですかね?

    2015年3月22日 5:32
  • > コードとかじゃなくIISの設定とかなんですかね?

    設定が関係あるとすると web.config の設定かもしれません。

    先にも書いたように自分は VS2010 の MVC4 インターネットアプリケーションテンプレートで自動生成される web.config をそのまま使っています。

    そのあたりの質問者さんとの違いは分かりません。

    asp.net mvc maproute period などをキーワードにググると、例えば以下のような記事が見つかります。自分が調べた限りでは今回の件とは関係なさそうですが、チェックしてみてください。

    Dots in URL causes 404 with ASP.NET mvc and IIS
    http://stackoverflow.com/questions/11728846/dots-in-url-causes-404-with-asp-net-mvc-and-iis

    Putting the Con (COM1, LPT1, NUL, etc.) Back in your URLs
    http://haacked.com/archive/2010/04/29/allowing-reserved-filenames-in-URLs.aspx/


    #全角 / 半角を間違えているというようなミスはないと思っていて良いのですよね?(そんな単純なミスはしないということでしたら失礼しました)
    • 編集済み SurferOnWww 2015年3月22日 8:19 #以下追記
    2015年3月22日 8:03
  • VS2010はすぐには試せなかったのでVS2012のMVC4のテンプレートでは試していたのですが同様でした

    元々のVS2013/MVC5の環境およびVS2012/MVC4のテンプレートでWeb.Configに以下を追加することで動作するようになりました。

    <modules runAllManagedModulesForAllRequests="true"/>

    2015年3月22日 12:29
  • > 元々のVS2013/MVC5の環境およびVS2012/MVC4のテンプレートでWeb.Configに以下を
    > 追加することで動作するようになりました。
    >
    > <modules runAllManagedModulesForAllRequests="true"/>

    それは自分の環境(VS2010)では、MVC3 でも MVC4 でも、さらには ASP.NET 4 なら Web Forms でも web.config に設定されています。質問者さんの環境では違うのでしょうか?

    さらに、先に書いた自分の環境でそれを false にしても 404 Not Found エラーにはならず、期待通りルーティングされたので関係ないと思ったのですが・・・

    以下のページを見ると、Service Pack 適用後は runAllManagedModulesForAllRequests の設定が false または設定無しでもルーティングに影響はなさそうだということが書いてありますが、そのあたりはどうなんでしょう?

    Modules <modules>
    http://www.iis.net/configreference/system.webserver/modules

    "Note: In ASP.NET websites, the value of runAllManagedModulesForAllRequests previously had to be set to true to support routing. However, once IIS 7 has been updated with a Service Pack, the value of runAllManagedModulesForAllRequests can be set to false or omitted when working with ASP.NET routing."

    最初に聞くべきだったかもしれませんが、質問者さんの環境を具体的に教えていただけませんか?

    2015年3月22日 15:10
  • > それは自分の環境(VS2010)では、MVC3 でも MVC4 でも、さらには ASP.NET 4 なら Web Forms でも web.config に設定されています。質問者さんの環境では違うのでしょうか?

    設定されてないですね。

    VS2013 Community/MVC5

    VS2012 Pro/MVC4

    Windowsは8.1 ProでIISは6.2ですね

    2015年3月23日 1:11
  • もう少し情報を提供いただけないでしょうか。ここは開発者同士の情報交換の場ということで、協力お願いします。

    > 設定されてないですね。

    使ったテンプレートが違うんでしょうかね。どのテンプレートを使ったか教えていただけませんか。残念ながら、自分の環境には VS2012 も VS2013 もないので確認できません。

    ちなみに、自分の環境の VS2010 の MVC4 インターネットアプリケーションのテンプレートで作ると、自動生成される web.config の system.webServer 要素には以下の設定がなされます。

    <system.webServer>
        <validation validateIntegratedModeConfiguration="false" />
        <modules runAllManagedModulesForAllRequests="true" />
        <handlers>
          <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
          <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
          <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
          <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" 
              path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" 
              modules="IsapiModule" 
              scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll"
              preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
          <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit"
              path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
              modules="IsapiModule"
              scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
              preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
          <add name="ExtensionlessUrlHandler-Integrated-4.0"
              path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
              type="System.Web.Handlers.TransferRequestHandler"
              preCondition="integratedMode,runtimeVersionv4.0" />
        </handlers>
    </system.webServer>
    

    > Windowsは8.1 ProでIISは6.2ですね

    Windows 8.1 なら IIS8.5 ですよね? それはともかく、検証の際は IIS 上でアプリを動かして行ったのですか? それとも ASP.NET 開発サーバーまたは IIS Express ですか? (先の質問者さんのレスで localhost:50970 とあったこと、VS2013 を使用ということで IIS Express と想像しているのですが)


    先に紹介した記事、

    Modules <modules>
    http://www.iis.net/configreference/system.webserver/modules

    で、Service Pack 適用後は runAllManagedModulesForAllRequests の設定が false または設定無しでもルーティングに影響はないと書いてありますが、それは KB980368 のようです。

    Windows 8.1 では適用外ですが、運用環境が Windows Server 2008R2 とかですと未適用の可能性もありそうです。その点も確認いただけますか?

    2015年3月23日 4:06
  • なぜ KB980368 が関係するのかですが・・・

    以下の記事の最初の方に KB980368 について触れています。

    How Extensionless URLs Are Handled By ASP.NET v4
    http://blogs.msdn.com/b/tmarq/archive/2010/05/26/how-extensionless-urls-are-handled-by-asp-net-v4.aspx

    上の記事の TransferRequestHandler ハンドラはデフォルトで path="*." と設定されています。(先のレスで書いた VS2010 のテンプレートによる web.config への設定はなくても、applicationHost.config で設定されています)

    ということは url の最後の文字がピリオドでないと TransferRequestHandler は要求をハンドルしないということになります。その不具合を修正するのが KB980368 ということです。詳しくは以下のページを見てください。

    A update is available that enables certain IIS 7.0 or IIS 7.5 handlers
    to handle requests whose URLs do not end with a period
    https://support.microsoft.com/en-us/kb/980368

    TransferRequestHandler が要求をハンドルしなければ、Home/Action/1200x800/sample.jpg という url は IIS StaticFile ハンドラで処理されるはずで、その結果 404 Not Found エラーになったものと思われます。


    ここから先は想像ですが・・・

    先に紹介した記事、

    Dots in URL causes 404 with ASP.NET mvc and IIS
    http://stackoverflow.com/questions/11728846/dots-in-url-causes-404-with-asp-net-mvc-and-iis

    で、path="/people/*" としたら解決したというのは、KB980368 に書いてある「最後の文字がピリオドでないと TransferRequestHandler は要求をハンドルしない」という問題を回避できた(即ち、/people/michael.phelps をハンドルできるようにした)からではないかと思われます。

    上に紹介した記事「How Extensionless URLs Are Handled By ASP.NET v4」には次のように書いてあります。

    "If you do not remap the handler, they will both issue a "child request" to the original URL, but ask IIS to ignore their handler mappings for this second request.  By default, the IIS StaticFile handler is what will be mapped to these URLs during the second request, and that will typically result in a 404 or 403, assuming that no such file or directory exists."

    "Alternatively use can a feature like URL Routing to remap the handler.  URL Routing allows you to define routes that send a URL to a specific handler.  It simply calls RemapHandler for you."

    つまり、TransferRequestHandler ハンドラが要求を処理すれば、ルーティング定義はハンドラを remap したのと同じことになるそうなので、Home/Action/1200x800/sample.jpg はルーティングモジュールに渡されて、期待通り処理されたということだと思います。

    もう一つの解決策 runAllManagedModulesForAllRequests="true" で Home/Action/1200x800/sample.jpg も期待通りルーティングされるようになったのは、TransferRequestHandler に関係なく、ルーティングモジュールを含む全ての Managed Modules が全ての要求に対して働き、期待通りルーティングされるようになったということだと思います。

    Home/Action/1200x800/sample-jpg の方が問題なかったのは、これも想像ですが、Home/Action/1200x800/sample.jpg と違って、IIS StaticFile ハンドラで処理されることはなく、ルーティングモジュールに渡され、期待通りルーティングされたものと思われます。


    KB980368 の修正プログラムは 2010 年 4 月発行と古く、Windows 8.1 は適用外のようで、質問者さんのケースでは関係ないかも知れませんが、一応チェックいただければと思います。


    • 編集済み SurferOnWww 2015年3月23日 5:57 誤字訂正
    2015年3月23日 5:44
  • >使ったテンプレートが違うんでしょうかね。どのテンプレートを使ったか教えていただけませんか。残念ながら、自分の環境には VS2012 も VS2013 もないので確認できません。
    どれと言われてもオンラインのではなく普通にVSのインストーラーでインストールされるやつですけど、どこかに管理番号みたいなのあるんですか?

    ・VS2012
    ASP.NET MVC 4 Webアプリケーション Visual C#
    テンプレート:インターネットアプリケーション
    ビューエンジン:Razor

    ・VS2013
    ASP.NET MVC Webアプリケーション Visual C#
    テンプレート:MVC
    コア参照:MVC、API

    Web.configに関してはVS2012の方はrunAllManagedModulesForAllRequestsが無い以外は全く同じです

    >> Windowsは8.1 ProでIISは6.2ですね
    >Windows 8.1 なら IIS8.5 ですよね?
    8.5.9600.16384でした。6.2はWindowsのバージョンですね(8から8.1にアップデートされたマシンです)一番目立つとこにあったので勘違いしました。

    > それはともかく、検証の際は IIS 上でアプリを動かして行ったのですか? それとも ASP.NET 開発サーバーまたは IIS Express ですか? (先の質問者さんのレスで localhost:50970 とあったこと、VS2013 を使用ということで IIS Express と想像しているのですが)
    開発環境でやってます。
    2015年3月25日 0:31
  • 情報提供ありがとうございます。

    質問者さんの環境 Windows 8.1 / IIS8.5, VS2012 / 21013 で、なぜ runAllManagedModulesForAllRequests="true" にしないとダメなのかは依然として謎ですが、そういうこともあったと記憶にとどめておくことにします。

    以下、2, 3 レスします。

    > どれと言われてもオンラインのではなく普通にVSのインストーラーでインストールされる
    > やつですけど、どこかに管理番号みたいなのあるんですか?

    管理番号ではなくて VS で新しいプロジェクトを作る時のテンプレートのことです。

    具体的には、VS2010 MVC4 のものですが、以下のページの上から 2 番目の画像のものです。

    VS2010 で ASP.NET MVC 4
    http://surferonwww.info/BlogEngine/post/2014/07/14/aspnet-mvc-4-on-visual-studio-2010-professional.aspx


    > Web.configに関してはVS2012の方はrunAllManagedModulesForAllRequestsが無い以外は全く
    > 同じです

    そのことについてこちらでも調べてみましたが、runAllManagedModulesForAllRequests="true" の設定は VS2012 RC 版でなくなったようです。

    以下のページの「Configuration Changes in ASP.NET 4.5 Website Templates」のセクションに書いてあります。

    What's New in ASP.NET 4.5 and Visual Studio 2012
    http://www.asp.net/aspnet/overview/aspnet-and-visual-studio-2012/whats-new

    その理由は、同じ記事の「Native Support in IIS 7 for ASP.NET Routing」のセクションに書いてありますが、"An update that was made to IIS 7 makes the runAllManagedModulesForAllRequests setting unnecessary and supports ASP.NET routing natively." ということです。

    要するに「update によって true にしなくてもルーティングが働くようになった。ture にすると余計なオーバーヘッドが増えるから」ということだそうです。

    その update というのが、以下の記事に書いてある、拡張子無しの URL を処理するハンドラの追加と KB980368 ということです。

    How Extensionless URLs Are Handled By ASP.NET v4
    http://blogs.msdn.com/b/tmarq/archive/2010/05/26/how-extensionless-urls-are-handled-by-asp-net-v4.aspx

    上の記事の話は、KB980368 が適用されているという条件付なのでそれをチェックしてくださいと前のレスで言いました。Windows 8.1 / IIS8.5 には関係なさそうですが、念のためチェックしてみてはいかがでしょう。


    > 開発環境でやってます。

    質問を理解されてないようです。開発環境で使っているサーバーは何ですかという質問です。VS2010, VS2012 であれば IIS / IIS Express / ASP.NET 開発サーバーのいずれかを利用できます。

    その違いの影響は結構大きいです。詳しくは以下のページ差参考になると思いますので、興味がおありでしたら見てください。

    ASP.NET 開発サーバーと IIS
    http://surferonwww.info/BlogEngine/post/2011/11/18/ASPNET-development-server-and-IIS.aspx

    ちなみに自分の検証結果は ASP.NET 開発サーバー上で試したときのものです。後日時間ができたら、今回の件について、IIS で試して、その違いによる影響を調べてみることにします。

    2015年3月25日 4:47
  • こんにちは。
    私も同じような事で詰まった事があったのですが、下記の記事などを参考に解決できました。
    下記の二つの記事はそれぞれ異なるアプローチから解決しているようです。
    要件に応じて選ぶ必要がありそうです。


    TransferRequestHandlerを利用するケース
    https://sakapon.wordpress.com/2014/04/19/routing-with-extension/


    RouteExistingFilesを利用するケース
    http://blog.shibayan.jp/entry/20110420/1303304598


    2015年3月27日 23:06
  • CharAzurable さん>

    > 私も同じような事で詰まった事があったのですが、下記の記事などを参考に解決できました。

    できれば、その「詰まった」時の CharAzurable さんの環境、どのような問題だったのか、どのように解決したのか(参考にされている記事ではどれのどこが解決につながったのか)を具体的に書いていただけないでしょうか?

    上のレスにも書きましたが、VS2012 RC 版では runAllManagedModulesForAllRequests="true" の設定を不要にして(なくてもルーティングが働くようにして)、VS2012 のテンプレートによる web.config の設定からはその設定を削除したずなのに、質問者さんの環境では開発者が追加しないとルーティングが働かず 404 Not Found になったというのが謎です。その理由のヒントになる情報を提供いただけると幸いです。


    CharAzurable さんが挙げられている記事についてレスします。

    > TransferRequestHandlerを利用するケース
    > https://sakapon.wordpress.com/2014/04/19/routing-with-extension/

    その記事は拡張子無しの URL を処理する HTTP ハンドラの話で、上のレスでも何度か話が出てきていますが、質問者さんの環境でもテンプレートによって web.config に設定済みとのことです。

    デフォルトで path="*." と設定されてるので url の最後の文字がピリオドでないと TransferRequestHandler は要求をハンドルしないということになりますが、その不具合は KB980368 で修正されているそうです。

    質問者さんの環境は Windows 8.1 / IIS8.5 ということなので、不具合は修正済みと思うのですが、実際どうなのかは分かりません。

    > RouteExistingFilesを利用するケース
    > http://blog.shibayan.jp/entry/20110420/1303304598

    それは URL で指定されるパスに物理ファイルが存在するとルーティングによって処理されないということへの対応策で、今回の質問者さんの問題とは関係なさそうです。

    2015年3月28日 2:22
  • 先の自分のレスで、

    > ちなみに自分の検証結果は ASP.NET 開発サーバー上で試したときのものです。後日時間ができたら、
    > 今回の件について、IIS で試して、その違いによる影響を調べてみることにします。

    と書きましたが、検証に使った Web アプリ(VS2010 Professional の MVC4 インターネットテンプレートで作成)を開発マシンの Vista Ultimate SP2 の IIS7 で動くようにして試してみました。

    結果 runAllManagedModulesForAllRequests(以下 RAMMFAR と書きます)を true に設定しないとルーティングが動きませんでした(404 Not Found エラーになる)。

    Service Pack は適用済みですし、KB980368 の更新プログラムをダウンロードしてインストールしようとしても適用外と出ます。

    KB980368 が適用済みなら ExtensionlessUrlHandler の設定(それはデフォルトで web.config に設定済み)によって RAMMFAR の設定を削除してもルーティングが動くという話でしたが・・・

    何故ダメなのかは調べきれてません。

    2015年3月30日 6:06
  • ワイルドカード スクリプト マッピングと IIS 7 統合パイプライン
    https://technet.microsoft.com/ja-jp/library/ff454109.aspx

    の最後にあるように、単純にpreCondition="ManagedHandler"が付いちゃってるだけ、ってことはないんですかね?

    ※確認したわけではなくて、単純にこれが理由てことはないのかな?と思っただけです。

    2015年3月30日 9:22