読者です 読者をやめる 読者になる 読者になる

きよくらの備忘録

「三日坊主と呼ばせない!日記」改め。主にソフトウェア開発関連の話題。

非同期ポストバック時でもリダイレクトはよしなにしてくれます。(僕が狂ってた)

先日書いた、
非同期ポストバック時に「やっぱり全面書き換え〜(というかリダイレクト)」って出来ない? - 三日坊主と呼ばせない!日記
ですが、完全に問題なかったというか、勘違いしていたというか。

今思うと何をトチ狂ってたのか不明なのですが、Response.Redirectは普通に扱ってくれますね。
ひょっとして、Server.Transferしてた所と勘違いしていたのかも……。

これだけだとただの間抜けなだけ……というか、折角いろいろ調べたので、メモっておきます*1

    • -

そもそも、本来Response.Redirectを行った場合、サーバからクライアントに対し、レスポンスコードとしては302、そして一緒にリダイレクト先のURIが返る。
そして、それを受け取ったクライアントがリダイレクト先のURLにGETを行う。

この動きをASP.NET AJAXの非同期ポストバック中にそのまま動かすには、当然無理がありすぎる。
しかし、一見、上っ面だけ見るとちゃんと動いてるように見えるのは何でだ……とは思うものの、まあ、カラクリは容易に想像がつく。
きっと、非同期ポストバックのレスポンスで、『hogehogeなURLにリダイレクトしてね』みたいな命令セットみたいなのを、JSONかXMLか独自形式かは知らないけど、とにかくテキストで返してクライアント側のコールバック関数で取得、そいつがlocation.hrefかなにかにセットしてジャンプしているに違いない。



とりあえずそれを確認するために、Web Development HelperでHTTPのログを見る。
するとやはり、非同期ポストバックからの応答は、レスポンスヘッダには200でContent-Type:text/plain、レスポンスコンテントには『14|pageRedirect||/Hogehoge.aspx|』みたいな内容が入っていることを確認。そしてその後のクライアント側の挙動は、普通にリダイレクト先のURLでGETのリクエストが飛んでいる。
非同期ポストバックに対するレスポンスコンテントの書式はおそらく、『|』区切りで『目的語の長さ|命令|?|目的語』みたいな感じになっていることが想像できる。

ということで、最初の想像は間違っていなかったことが解った。


ということは、サーバ側……というかASP.NETのプロセス側では、
・何らかの手段でRedirectのレスポンスが発生を(クライアントに返す前にサーバ内で)キャッチ
・現在のリクエストが非同期通信であるか判断、そうであった場合は上記の命令セットを構築し、適切なヘッダを付加して送出
というような作業をしているに違いない。

が、これ以上は自力では如何ともしがたいのでgoogleさんにお伺いをたてると……見つかりました。

http://www.manuelabadia.com/blog/PermaLink,guid,31a01aba-565d-46ab-b8af-bde3352905c9.aspx

つまり、httpModulesとして追加した*2ScriptModuleが、302で返す時にそれを横取りし、上記の命令セットを積み込んで返す。そして、受け取ったJavascriptのコールバック関数側でそれを解析、本来のRedirect先にGETをかける、と。

いや、やっぱり良くできてますね、ASP.NET AJAX。<なにをぬけぬけと


一点注意点があるとすれば、本来リダイレクトならは302が返るとこだけれど、こういった挙動をせざるを得ないために200で返る、ということでしょうか。
ま、使う場面的に、あまり問題になることはなさそうですけど。

*1:どのみち間抜けには変わりありませんが

*2:ScriptManagerを張り付けると、Web.Configには勝手に追記される