none
ASP.Net MVCのルーティングとIISのリライトについて RRS feed

  • 質問

  • お世話になります。

    ASP.Net MVC5を利用してWebアプリケーションを開発しております。

    特定のURLについて、IISのリライト設定で、リバースプロキシ動作するように設定しようとしているのですが、MVCのルーティング設定のほうが、IISのリライト設定よりも先に動作してしまい、IISのリライトがうまく動作してくれません。

    例えば http://hoge.jp/info/ にアクセスした場合、yahooを表示するとしますと、リライト設定を以下のようにします。

    <rewrite>
    	<rules>
    		<rule name="ReverseProxyInboundRule1" stopProcessing="true">
    			<match url="^info/$" />
    			<action type="Rewrite" url="http://www.yahoo.co.jp/" />
    		</rule>
    	</rules>
    </rewrite>

    しかしながら、以下のようなMVC側でデフォルトのルーティング設定がされていると、

    	public class RouteConfig
    	{
    		public static void RegisterRoutes(RouteCollection routes)
    		{
    			routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
    			routes.MapRoute(
    				name: "Default",
    				url: "{controller}/{action}/{id}",
    				defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    			);
    		}
    	}

    上記ルーティング設定が動作してしまい、infoコントローラが内という事で404が返ります。

    ちなみにinfoコントローラを作成すると、そのコントローラが動作します。


    私の認識では、MVCのルーティングよりも先に、IIS側のリライトが適用されるものと認識しております。

    しかしながら私が試した環境では、MVCのルーティングの条件から漏れた場合のみ、リライトが動作しています。

    私の認識は間違っていますでしょうか。MVCのルーティングよりも先にIISのリライトを動作さえる事はできないのでしょうか。

    試した環境は、Windows10 x64 Pro  IIS 10.0 + ASP.Net MVC 5

    および Azure Web Apps  + ASP.Net MVC 5 です。

    ご教示頂けますと幸いです。

    よろしくお願いいたします。

    2016年11月2日 9:39

回答

  • 問題が解決できましたので、解決手法について共有致します。

    下記のページで、MVCのルーティングを特定条件で停止する手法が記載されていました。

    https://msdn.microsoft.com/ja-jp/library/cc668201(v=vs.110).aspx#ルーティングが適用されないときのシナリオ

    具体的にはStopRoutingHandlerをRouteConfigに追記しました。

    public class RouteConfig
    {
    	public static void RegisterRoutes(RouteCollection routes)
    	{
    		routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
    		routes.Add(new Route("info/{*pathInfo}", new System.Web.Routing.StopRoutingHandler()));//追加
    
    		routes.MapRoute(
    			name: "Default",
    			url: "{controller}/{action}/{id}",
    			defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    		);
    	}
    }


    これにより、/info/以下のURLは、MVCのルーティング処理から外れ、IIS側にそのまま制御が移るようになり、ARRのリライトによるリバースプロクシが動くようになりました。

    情報ありがとうございました。またお騒がせ致しました。



    • 回答としてマーク 星 睦美 2016年11月14日 4:07
    2016年11月10日 5:56

すべての返信

  • type="Rewrite" ではなくて type="Redirect" が正しいような気がします。

    気がするだけで検証はしていませんので、間違っていたらすみません。とりあえず試してみて、結果を連絡いただればと思います。
    2016年11月2日 11:22
  • ありがとうございます。

    type="Redirect" としても変化はありませんでした。

    ちなみに、MVCのルーティングの条件から外した設定にした場合は、yahooへリダイレクトされることは確認できました。当然リライトの動作としては正常ですが、リバースプロクシの動きをさせたいので、これは期待する動作ではありません・・・。

    なお通常のよくあるリライト設定、つまりURLを/info/ → /test/とするような設定にしたとしても、変化はありません。

    MVC側が先に拾って処理してしまう状態から変化せずでした。

    リライトが先に動作しない、何かしら致命的な設定ミスがあるのでしょうか・・・


    2016年11月2日 12:37
  • リダイレクトされないと言うので、自分の環境(Vista SP2 32-bit, ローカル IIS7, MVC4)で試してみましたが期待通りリダイレクトされました。質問者さんのやり方の問題 or 環境の違いなのでしょうかね。何が違うのかは分かりませんが・・・

    URL 書換規則は IIS マネージャーから GUI 画面で設定して以下の通りです。

     
    <rewrite>
        <rules>
            <rule name="RedirectTest" stopProcessing="true">
                <match url="^route/$" />
                <action type="Redirect" url="http://surferonwww.info/" />
            </rule>
        </rules>
    </rewrite>

    RouteConfig.cs はデフォルト(質問者さんのと同じ内容)です。

    以下の画像の通り /route/ を要求すると(反転された #17 行を見てください。mvc4application はローカル IIS7 で設定したサイト名)、右下の Response Headers に示すとおり 301 応答が返ってきて Location に URL 書換規則で設定したリダイレクト先 http://surferonwww.info/ が指定されています。

    次の行 #18 で、ブラウザは  Location に指定された http://surferonwww.info/ を GET 要求に行っています。

    2016年11月3日 1:54
  • 詳しくテストして頂き、また画面キャプチャまで頂きありがとうございます。

    あれから数回プロジェクトを作り直して、同様に試したところ、リダイレクトはうまくいくようになりました。何かの残骸が悪さをしていたのかも知れません。大変お騒がせ致しました。

    これでIISのリライトが、MVCのルーティングより先行して動作していることが確認できました。

    まだtype="Rewrite" での404問題が解決できておりませんが、これはリライト後のURLが意図したものとなっていない可能性が高いため、引き続きログを調査し、チャレンジしてみます。解決できましたらご報告いたします。


    この度はお力添えを頂きましてありがとうございました。


    2016年11月7日 1:53
  • type="Redirect"とtype="Rewrite"の挙動が整理できましたので、ご報告いたします。

    前提としまして、以下のサイトを参考にリバースプロキシを設定しております。

    ■IISのApplication Request Routing(ARR)でリバースプロキシを構築する
    https://codezine.jp/article/detail/7018


    わかりやすいように、今回は
     <match url="(.*)" />
    と全てのURLを対象にして、実験しました。


    そのうえで、開発サイトをlocalhostとし、
    http://localhost/
    とアクセスした場合の挙動です。

    ▼<action type="Redirect" url="http://hoge.jp/" /> とした場合

    IIS側で即座にhttp://hoge.jp/リダイレクトされます。
    MVC側のコントローラに制御が来ることはないようです。


    ▼<action type="Rewrite" url="http://hoge.jp/" /> とした場合

    MVC側のRouteConfigで設定された、デフォルトの設定であるHomeコントローラのIndexアクションが呼び出されます。

    出力されたHTMLで指定された、MVC制御外のその他のリソース、例えば/css/common.cssは、IISのリバースプロクシを通して http://hoge.jp/css/common.css にリクエストされています。


    上記をまとめると、

    action type="Rewrite" とした場合、match url="" で指定されたURLと、MVC側のRouteConfigでMapRouteでマッピングされたコントローラおよびアクションが存在した場合は、MVC側のコントローラが動作し、存在しない場合はIISのリライト(リバースプロキシ)が動作する。

    というような挙動となりました。
    私の環境では、上記結果となっています。


    解決策としては、action type="Rewrite"を使う場合、MVC側のMapRouteで、match url=""で指定されたURLとかぶらないような条件を設定するしかないのかなと思っております。


    上記解決策でなんとかしていくつもりですが、何かうまいやり方が見つかりましたらご報告いたします。

    2016年11月7日 2:58
  • > 前提としまして、以下のサイトを参考にリバースプロキシを設定しております。
    > ■IISのApplication Request Routing(ARR)でリバースプロキシを構築する
    https://codezine.jp/article/detail/7018

    一番最初の質問と話が違ってきてませんか? 一番最初の質問ではタイトルの、

    > ASP.Net MVCのルーティングとIISのリライトについて

    にありますように、IIS7+ の URL Rewrite Module と ASP.NET Routing の話だったと思ってましたが・・・

    ARR というのは自分は触ったこともないので、それが絡むとどういう動作になるのかは分かりません。


    • 編集済み SurferOnWww 2016年11月7日 6:09 typo 訂正
    2016年11月7日 3:41
  • 大変失礼致しました。

    「URLリライトのリバースプロキシ」と記載したものの、ARRは記載がありませんでした。

    ご迷惑をおかけして申し訳ございません。

    2016年11月7日 8:07
  • 問題が解決できましたので、解決手法について共有致します。

    下記のページで、MVCのルーティングを特定条件で停止する手法が記載されていました。

    https://msdn.microsoft.com/ja-jp/library/cc668201(v=vs.110).aspx#ルーティングが適用されないときのシナリオ

    具体的にはStopRoutingHandlerをRouteConfigに追記しました。

    public class RouteConfig
    {
    	public static void RegisterRoutes(RouteCollection routes)
    	{
    		routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
    		routes.Add(new Route("info/{*pathInfo}", new System.Web.Routing.StopRoutingHandler()));//追加
    
    		routes.MapRoute(
    			name: "Default",
    			url: "{controller}/{action}/{id}",
    			defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    		);
    	}
    }


    これにより、/info/以下のURLは、MVCのルーティング処理から外れ、IIS側にそのまま制御が移るようになり、ARRのリライトによるリバースプロクシが動くようになりました。

    情報ありがとうございました。またお騒がせ致しました。



    • 回答としてマーク 星 睦美 2016年11月14日 4:07
    2016年11月10日 5:56