IIS7 の 404 + HttpHandler にフォームを投稿します。POST データがすべて失われているのはなぜですか?
-
01-07-2019 - |
質問
OK、これは少し混乱して複雑に聞こえるかもしれませんが、ご了承ください。
フレンドリーな URL を定義できるフレームワークを作成しました。任意の URL にアクセスすると、IIS は 404 エラー (場合によっては 403;14 または 405) を表示しようとします。ただし、IIS は、これらの特定のエラーに関連するものはすべて .aspx ファイルに送信されるように設定されています。これにより、HttpHandler を実装してリクエストを処理したり、関連するテンプレートを見つけて、それに関連付けられたものを実行したりすることができます。
さて、これはすべて IIS 5 と 6、そしてある程度は IIS7 でも機能しますが、フォームを投稿するときに発生する 1 つの問題点があります。
存在しない URL にフォームを投稿すると、IIS は「ああ、でもその URL は存在しません」と言って、405「メソッドが許可されていません」エラーをスローします。これらのエラーを .aspx ページにリダイレクトし、HttpHandler で処理するように IIS に指示しているため、通常、これは問題になりません。しかし、IIS7 では、すべての POST 情報が 405 にリダイレクトされた後に失われています。そのため、フォームに関係する最も些細な作業はできなくなります。
これを解決するために、HttpModule を使用してみました。これは POST データを保存しますが、適切なタイミング (必要なとき) にセッションが初期化されていないように見えます。また、404/403;14/405 にヒットした欠落リクエストだけでなく、すべてのリクエストに対して HttpModule を使用することも試みましたが、これは画像、CSS、JS などのものが .NET コードによって処理されることを意味し、非常に非効率的です。
ここで実際の質問に移ります。誰かがこれに遭遇したことがありますか、誰かが何かアドバイスを持っているか、物事を再び動作させるために何をすべきか知っていますか?これまでのところ、誰かがMicrosoft独自のものを使用することを提案しています URL書き換えモジュール. 。これは問題の解決に役立つでしょうか?
ありがとう。
解決
Microsoft はこれに対するホットフィックスをリリースしました。
他のヒント
IIS7 はトップダウンで .net を使用するため、HttpModule の使用によるパフォーマンスのオーバーヘッドはありません。実際、すべての要求で常に使用される管理対象 HttpModule がいくつかあります。BeginRequest イベントが発生したときに、SessionStateModule が Modules コレクションに追加されていない可能性があるため、このイベント中にリクエストを処理しようとしても、セッション状態情報は利用できません。HttpContext.Handler プロパティを設定すると、要求されたハンドラーが必要とする場合にセッション状態が初期化されるため、ハンドラーを IRequiresSessionState を実装する派手な 404 ページに設定するだけで済みます。以下のコードでうまくいきますが、IsMissing() メソッドの別の実装を記述する必要がある場合があります。
using System.Web;
using System.Web.UI;
class Smart404Module : IHttpModule
{
public void Dispose() {}
public void Init(HttpApplication context)
{
context.BeginRequest += new System.EventHandler(DoMapping);
}
void DoMapping(object sender, System.EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
if (IsMissing(app.Context))
app.Context.Handler = PageParser.GetCompiledPageInstance(
"~/404.aspx", app.Request.MapPath("~/404.aspx"), app.Context);
}
bool IsMissing(HttpContext context)
{
string path = context.Request.MapPath(context.Request.Url.AbsolutePath);
if (System.IO.File.Exists(path) || (System.IO.Directory.Exists(path)
&& System.IO.File.Exists(System.IO.Path.Combine(path, "default.aspx"))))
return true;
return false;
}
}
編集:IsMissing() の実装を追加しました
注記:IIS7 では、セッション状態モジュールはデフォルトではグローバルに実行されません。次の 2 つのオプションがあります。すべてのリクエストに対してセッション状態モジュールを有効にするか (すべてのリクエスト タイプに対するマネージド モジュールの実行に関する上記のコメントを参照)、リフレクションを使用して System.Web.dll 内の内部メンバーにアクセスすることもできます。
IIS 7 でポスト変数がカスタム エラー ハンドラーに渡されないという問題は、Vista の Service Pack 2 で修正されています。Windows Server では試していませんが、Windows Server でも修正されると思います。
単なる推測です:リクエストを処理する IIS7 の %windir%\system32\inetsrv\config\applicationhost.config で指定されたハンドラーは、POST 動詞の通過をまったく許可しておらず、URL が存在するかどうかを判断する前にそのルールを評価しています。 。
はい、URL の書き換え (Microsoft の IIS7 の 1 つまたは多くの代替手段の 1 つを使用) を間違いなくお勧めします。これはわかりやすい URL を提供するために特別に設計されていますが、エラー ドキュメントは障害に対する最後の手段であり、受信データが変更される傾向があるため、期待どおりにならない可能性があります。