Thông thường, tất cả những gì bạn cần là thực hiện một số trạng thái giữa hai yêu cầu này. Thực sự có một cách thực sự thú vị để làm điều này mà không dựa vào JavaScript (nghĩ <noscript />).
Set-Cookie: name=value; Max-Age=120; Path=/redirect.html
Với cookie đó, bạn có thể yêu cầu /redirect.html lấy thông tin name = value sau đây, bạn có thể lưu trữ bất kỳ loại thông tin nào trong chuỗi cặp tên / giá trị này, tối đa là 4K dữ liệu (giới hạn cookie thông thường). Tất nhiên, bạn nên tránh điều này và lưu trữ mã trạng thái và các bit cờ thay thế.
Khi nhận được yêu cầu này, bạn sẽ đáp lại yêu cầu xóa mã trạng thái đó.
Set-Cookie: name=value; Max-Age=0; Path=/redirect.html
HTTP của tôi hơi bị rỉ sét Tôi đã sử dụng RFC2109 và RFC2965 để tìm hiểu mức độ đáng tin cậy của nó, tốt nhất là tôi muốn cookie thực hiện một chuyến đi chính xác một lần nhưng dường như cũng không thể, cookie của bên thứ ba có thể là một vấn đề cho bạn nếu bạn chuyển sang tên miền khác. Điều này vẫn có thể nhưng không đau đớn như khi bạn làm công việc trong miền của riêng bạn.
Vấn đề ở đây là sự tương tranh, nếu một người dùng quyền lực đang sử dụng nhiều tab và quản lý để xen kẽ một vài yêu cầu thuộc cùng một phiên (điều này rất khó xảy ra, nhưng không phải là không thể), điều này có thể dẫn đến sự không nhất quán trong ứng dụng của bạn.
Đó là cách <noscript /> thực hiện các chuyến đi vòng HTTP mà không cần URL và JavaScript vô nghĩa
Tôi cung cấp mã này dưới dạng khái niệm: Nếu mã này được chạy trong ngữ cảnh mà bạn không quen thuộc, tôi nghĩ bạn có thể tìm ra phần nào là gì.
Ý tưởng là bạn gọi Relocate với một số trạng thái khi bạn chuyển hướng và URL mà bạn đã di chuyển gọi GetState để lấy dữ liệu (nếu có).
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;
}