通常、必要なのは、これら 2 つのリクエスト間で何らかの状態を保持することだけです。これを行うには、JavaScript に依存しない非常にファンキーな方法があります (<noscript/> を考えてください)。
Set-Cookie: name=value; Max-Age=120; Path=/redirect.html
その Cookie を使用すると、/redirect.html への次のリクエストで name=value 情報を取得できます。この名前と値のペアの文字列には、最大 4K のデータ (通常の Cookie 制限) まで、あらゆる種類の情報を格納できます。もちろん、これは避けて、代わりにステータス コードとフラグ ビットを保存する必要があります。
このリクエストを受け取ったら、そのステータス コードの削除リクエストで応答します。
Set-Cookie: name=value; Max-Age=0; Path=/redirect.html
私の HTTP は少し錆びています。RFC2109 と RFC2965 を調べて、これが実際にどれほど信頼できるかを調べてきました。できれば、Cookie を正確に 1 回往復させたいのですが、それは可能ではないようです。また、サードパーティの Cookie別のドメインに移転する場合、これが問題になる可能性があります。これはまだ可能ですが、独自のドメイン内で何かをしている場合ほど簡単ではありません。
ここでの問題は同時実行性です。パワー ユーザーが複数のタブを使用していて、同じセッションに属するいくつかのリクエストをインターリーブすることができた場合 (これはほとんどありませんが、不可能ではありません)、アプリケーションに矛盾が生じる可能性があります。
無意味な URL や JavaScript を使用せずに HTTP ラウンド トリップを行う <noscript/> 方法です。
このコードを概念の教授として提供します。このコードがよく知られていないコンテキストで実行される場合、どの部分が何であるかを理解できると思います。
リダイレクト時に何らかの状態で Relocate を呼び出し、再配置した URL が GetState を呼び出してデータ (存在する場合) を取得するという考え方です。
const string StateCookieName = "state";
static int StateCookieID;
protected void Relocate(string url, object state)
{
var key = "__" + StateCookieName + Interlocked
.Add(ref StateCookieID, 1).ToInvariantString();
var absoluteExpiration = DateTime.Now
.Add(new TimeSpan(120 * TimeSpan.TicksPerSecond));
Context.Cache.Insert(key, state, null, absoluteExpiration,
Cache.NoSlidingExpiration);
var path = Context.Response.ApplyAppPathModifier(url);
Context.Response.Cookies
.Add(new HttpCookie(StateCookieName, key)
{
Path = path,
Expires = absoluteExpiration
});
Context.Response.Redirect(path, false);
}
protected TData GetState<TData>()
where TData : class
{
var cookie = Context.Request.Cookies[StateCookieName];
if (cookie != null)
{
var key = cookie.Value;
if (key.IsNonEmpty())
{
var obj = Context.Cache.Remove(key);
Context.Response.Cookies
.Add(new HttpCookie(StateCookieName)
{
Path = cookie.Path,
Expires = new DateTime(1970, 1, 1)
});
return obj as TData;
}
}
return null;
}