Response.Redirect กับ POST แทนที่จะเป็น Get?


248

เรามีข้อกำหนดในการส่งแบบฟอร์มและบันทึกข้อมูลจากนั้นเปลี่ยนเส้นทางผู้ใช้ไปยังหน้านอกสถานที่ แต่ในการเปลี่ยนเส้นทางเราจำเป็นต้อง "ส่ง" แบบฟอร์มด้วย POST ไม่ใช่ GET

ฉันหวังว่าจะมีวิธีที่ง่ายในการทำสิ่งนี้ แต่ฉันเริ่มคิดว่าไม่มี ฉันคิดว่าตอนนี้ฉันจะต้องสร้างหน้าอื่น ๆ ที่เรียบง่ายมีเพียงรูปแบบที่ฉันต้องการเปลี่ยนไปใช้เติมแบบฟอร์มตัวแปรจากนั้นทำการเรียก body.onload สคริปต์ที่เพียงเรียก document.forms [0] .submit ( );

ใครสามารถบอกฉันว่ามีทางเลือกอื่นหรือไม่? เราอาจจำเป็นต้องปรับแต่งในภายหลังในโครงการและมันอาจจะซับซ้อนดังนั้นถ้ามีเรื่องง่ายเราสามารถทำได้ทั้งหมดไม่ใช่หน้าที่อื่นขึ้นอยู่กับว่าจะน่าอัศจรรย์

อย่างไรก็ตามขอบคุณสำหรับคำตอบใด ๆ และทั้งหมด


ใน PHP คุณสามารถส่งข้อมูล POST ด้วย cURL มีสิ่งที่เปรียบได้สำหรับ. NET?
Brian Warshaw

ฉันคิดว่านี่เป็นคำตอบง่ายๆที่คุณกำลังมองหา ฉันไม่อยากจะเชื่อเลยว่ามันช่างฉลาด
เหลือเกิน

@BrianWarshaw ฉันค้นหา System.Net.Http.HttpClient msdn.microsoft.com/en-us/library/…ใช้งานง่ายและรวดเร็วมาก
Stoyan Dimov

คำตอบ:


228

การทำเช่นนี้ต้องการความเข้าใจว่า HTTP redirects ทำงานอย่างไร เมื่อคุณใช้Response.Redirect()คุณจะส่งการตอบกลับ (ไปยังเบราว์เซอร์ที่ทำการร้องขอ) ด้วยรหัสสถานะ HTTP 302ซึ่งจะบอกเบราว์เซอร์ว่าจะไปที่ไหนต่อไป ตามคำนิยามเบราว์เซอร์จะทำให้ที่ผ่านคำขอแม้ว่าคำขอเดิมเป็นGETPOST

ตัวเลือกอื่นคือใช้รหัสสถานะ HTTP 307ซึ่งระบุว่าเบราว์เซอร์ควรทำการร้องขอการเปลี่ยนเส้นทางในลักษณะเดียวกับคำขอต้นฉบับ แต่เพื่อแจ้งผู้ใช้ด้วยคำเตือนความปลอดภัย ในการทำเช่นนั้นคุณจะเขียนดังนี้:

public void PageLoad(object sender, EventArgs e)
{
    // Process the post on your side   

    Response.Status = "307 Temporary Redirect";
    Response.AddHeader("Location", "http://example.com/page/to/post.to");
}

น่าเสียดายที่นี่ไม่ได้ผลเสมอไป เบราว์เซอร์ที่แตกต่างกันใช้สิ่งนี้แตกต่างกันเนื่องจากไม่ใช่รหัสสถานะทั่วไป

อนิจจาซึ่งแตกต่างจากนักพัฒนา Opera และ FireFox นักพัฒนา IE ไม่เคยอ่านข้อมูลจำเพาะและแม้แต่ IE7 ที่ปลอดภัยที่สุดล่าสุดจะเปลี่ยนเส้นทางคำขอ POST จากโดเมน A ไปยังโดเมน B โดยไม่มีคำเตือนหรือกล่องโต้ตอบการยืนยัน! Safari ยังทำหน้าที่ในลักษณะที่น่าสนใจในขณะที่ไม่เพิ่มการโต้ตอบการยืนยันและทำการเปลี่ยนเส้นทางมันจะทิ้งข้อมูล POST เปลี่ยนการเปลี่ยนเส้นทาง 307 เป็น 302 ที่มีประสิทธิภาพมากขึ้น

ดังนั้นเท่าที่ฉันรู้วิธีเดียวที่จะใช้บางสิ่งเช่นนี้คือการใช้ Javascript มีสองตัวเลือกที่ฉันสามารถนึกได้จากส่วนบนของหัวของฉัน:

  1. สร้างแบบฟอร์มและให้แอactionททริบิวชี้ไปที่เซิร์ฟเวอร์ของบุคคลที่สาม จากนั้นเพิ่มเหตุการณ์คลิกไปที่ปุ่มส่งที่เรียกใช้งาน AJAX ครั้งแรกไปยังเซิร์ฟเวอร์ของคุณด้วยข้อมูลจากนั้นอนุญาตให้ส่งแบบฟอร์มไปยังเซิร์ฟเวอร์บุคคลที่สาม
  2. สร้างแบบฟอร์มเพื่อโพสต์ไปยังเซิร์ฟเวอร์ของคุณ เมื่อมีการส่งแบบฟอร์มแสดงหน้าผู้ใช้ที่มีแบบฟอร์มพร้อมข้อมูลทั้งหมดที่คุณต้องการส่งต่อทั้งหมดในอินพุตที่ซ่อนอยู่ เพียงแสดงข้อความเช่น "การเปลี่ยนเส้นทาง ... " จากนั้นเพิ่มเหตุการณ์จาวาสคริปต์ไปยังหน้าเว็บที่ส่งแบบฟอร์มไปยังเซิร์ฟเวอร์บุคคลที่สาม

ในสองเรื่องนี้ฉันจะเลือกข้อที่สองด้วยสองเหตุผล ครั้งแรกมันมีความน่าเชื่อถือมากกว่าครั้งแรกเพราะ Javascript ไม่จำเป็นสำหรับการทำงาน; สำหรับผู้ที่ไม่ได้เปิดใช้งานคุณสามารถทำให้ปุ่มส่งสำหรับแบบฟอร์มที่ซ่อนอยู่สามารถมองเห็นได้และแนะนำให้พวกเขากดถ้ามันใช้เวลามากกว่า 5 วินาที ประการที่สองคุณสามารถตัดสินใจได้ว่าข้อมูลใดที่ถูกส่งไปยังเซิร์ฟเวอร์บุคคลที่สาม ถ้าคุณใช้เพียงแค่ประมวลผลแบบฟอร์มตามที่คุณต้องการคุณจะผ่านข้อมูลโพสต์ทั้งหมดซึ่งไม่ได้เป็นอย่างที่คุณต้องการ เช่นเดียวกับโซลูชัน 307 สมมติว่ามันใช้งานได้กับผู้ใช้ทั้งหมดของคุณ

หวังว่านี่จะช่วยได้!


1
กรุณาเปลี่ยน "เพิ่มเหตุการณ์คลิกไปที่ปุ่มส่ง" เป็น "เพิ่มเหตุการณ์ส่งไปยังแบบฟอร์ม" มีมากกว่าหนึ่งวิธีในการส่งแบบฟอร์มเช่นกด Enter ด้วยการป้อนข้อความที่มุ่งเน้นให้ส่งคนเดียวโดยทางโปรแกรม
temoto

122

คุณสามารถใช้ aproach นี้:

Response.Clear();

StringBuilder sb = new StringBuilder();
sb.Append("<html>");
sb.AppendFormat(@"<body onload='document.forms[""form""].submit()'>");
sb.AppendFormat("<form name='form' action='{0}' method='post'>",postbackUrl);
sb.AppendFormat("<input type='hidden' name='id' value='{0}'>", id);
// Other params go here
sb.Append("</form>");
sb.Append("</body>");
sb.Append("</html>");

Response.Write(sb.ToString());

Response.End();

ผลที่ตามมาหลังจากลูกค้าจะได้รับ html ทั้งหมดจากเซิร์ฟเวอร์เหตุการณ์onloadเกิดขึ้นซึ่งก่อให้เกิดการส่งแบบฟอร์มและโพสต์ข้อมูลทั้งหมดไปยัง postbackUrl ที่กำหนดไว้


9
+1 (ฉันจะบวกคุณมากกว่านี้ถ้าทำได้) นี่คือคำตอบ ฝีปากและตรงประเด็น คุณยังรวมรหัสทั้งหมดที่จะทำแทนการพูดออกจากส่วนหัวของคุณ ฉันใช้สิ่งนี้ใน iframe บนหน้า aspx ของฉันและทำให้ทุกอย่างสมบูรณ์แบบ - ไม่มีการเขียน URL ใหม่ เยี่ยมมาก! เคล็ดลับสำหรับผู้ที่ใช้ iframe: ฉันนำ iframe ของฉันไปยังหน้า aspx อื่นที่รันโค้ดนี้
MikeTeeVee

1
มันใช้งานได้! สิ่งที่แย่อย่างเดียวที่ฉันเห็นคือถ้าคุณกดปุ่มย้อนกลับของเบราว์เซอร์มันจะทำตามคำขออีกครั้งดังนั้นคุณจึงไม่สามารถเข้าถึงหน้าก่อนหน้าได้อีกต่อไป มีวิธีแก้ปัญหาสำหรับสิ่งนั้นหรือไม่?
ภูเขา Schneiders

4
มีเหตุผลที่วิธีการที่ได้รับการสนับสนุนสำหรับการทำเช่นนี้คือใช้ 307 การกระทำ POST มีวัตถุประสงค์เพื่อเป็นธุรกรรม idempotent คำตอบนี้เป็นเพียงแฮ็คที่เกิดขึ้นกับการทำงานและสามารถถูกบล็อกได้อย่างง่ายดายโดยเบราว์เซอร์ในอนาคต
Sam Rueby

2
@ จุดดี ในฐานะที่เป็นอาร์กิวเมนต์โต้: ตามคำตอบด้านบนนักพัฒนา IE ไม่ได้อ่านประมาณ 307 คนอื่น ๆ ที่อ่านมันดำเนินการอย่างผิดพลาด นั่นหมายความว่า 307 ชัดเจนว่าทำให้เกิดความสับสนกับ smarts (สมมติว่านักพัฒนาเบราว์เซอร์ฉลาด) และมีแนวโน้มที่จะเกิดข้อผิดพลาดในการตีความ วิธีการข้างต้นมีความชัดเจนอย่างน้อยสำหรับฉันและทำงานได้ในเบราว์เซอร์ทั้งหมดในอดีตและปัจจุบัน ไม่ต้องกังวลเกี่ยวกับอนาคตเนื่องจากนักพัฒนาของเราต่อสู้กับอดีต (อ่าน IE7) และแสดงวันเข้า / ออก IMHO เนื่องจากทุกคนได้รับอย่างถูกต้องพวกเขาควรเก็บไว้ตามเดิม เหตุผลในการปิดกั้นในอนาคตจะเป็นอย่างไร
so_mv

2
สิ่งนี้ไม่ได้มีประสิทธิภาพเหมือนกับตัวเลือกที่สองโดย TGHW หรือไม่ คุณไม่ได้อาจขอให้ใครบางคนประมาทเพื่อแนะนำช่องโหว่ XSS หรือไม่?
สกอตต์

33

HttpWebRequest ใช้สำหรับสิ่งนี้

บน postback ให้สร้าง HttpWebRequest ไปยังบุคคลที่สามและโพสต์ข้อมูลในแบบฟอร์มจากนั้นเมื่อทำเสร็จแล้วคุณสามารถ Response.Redirect ทุกที่ที่คุณต้องการ

คุณจะได้รับประโยชน์เพิ่มเติมที่คุณไม่ต้องตั้งชื่อการควบคุมเซิร์ฟเวอร์ทั้งหมดของคุณเพื่อสร้างฟอร์มบุคคลที่ 3 คุณสามารถทำการแปลนี้เมื่อสร้างสตริง POST

string url = "3rd Party Url";

StringBuilder postData = new StringBuilder();

postData.Append("first_name=" + HttpUtility.UrlEncode(txtFirstName.Text) + "&");
postData.Append("last_name=" + HttpUtility.UrlEncode(txtLastName.Text));

//ETC for all Form Elements

// Now to Send Data.
StreamWriter writer = null;

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";                        
request.ContentLength = postData.ToString().Length;
try
{
    writer = new StreamWriter(request.GetRequestStream());
    writer.Write(postData.ToString());
}
finally
{
    if (writer != null)
        writer.Close();
}

Response.Redirect("NewPage");

อย่างไรก็ตามหากคุณต้องการให้ผู้ใช้เห็นหน้าการตอบสนองจากแบบฟอร์มนี้ตัวเลือกเดียวของคุณคือการใช้ Server.Transfer และอาจทำงานได้หรือไม่ก็ได้


มันคือสิ่งที่ฉันจะใช้ถ้าฉันต้องการรูปแบบพิเศษกว่ารูปแบบ asp.net ฉันต้องโพสต์ข้อมูลบางอย่างไปยัง url ภายนอกซึ่งใช้สำหรับการชำระเงินที่ปลอดภัย 3d จากนั้นฉันต้องได้รับข้อมูลที่ส่งคืนจากคำขอ นี่เป็นวิธีการทำเช่นนี้หรือไม่? ขอขอบคุณ
Barbaros Alp

หากคุณต้องการให้ผู้ใช้เห็นการตอบสนองคุณสามารถส่งกลับเนื้อหาและส่วนหัวที่เหมาะสม คุณอาจต้องแก้ไขบางแง่มุมของผลขึ้นอยู่กับการใช้ทรัพยากรที่เกี่ยวข้อง แต่เป็นไปได้อย่างแน่นอน
Thomas S. Trias

6
ผู้ใช้อาจมีข้อมูลคุกกี้ที่จะไม่ถูกส่งผ่านวิธีนี้เนื่องจากเกิดขึ้นจากเซิร์ฟเวอร์
Scott

7

สิ่งนี้จะทำให้ชีวิตง่ายขึ้นมาก คุณสามารถใช้เมธอด Response.RedirectWithData (... ) ในเว็บแอปพลิเคชันของคุณได้อย่างง่ายดาย

Imports System.Web
Imports System.Runtime.CompilerServices

Module WebExtensions

    <Extension()> _
    Public Sub RedirectWithData(ByRef aThis As HttpResponse, ByVal aDestination As String, _
                                ByVal aData As NameValueCollection)
        aThis.Clear()
        Dim sb As StringBuilder = New StringBuilder()

        sb.Append("<html>")
        sb.AppendFormat("<body onload='document.forms[""form""].submit()'>")
        sb.AppendFormat("<form name='form' action='{0}' method='post'>", aDestination)

        For Each key As String In aData
            sb.AppendFormat("<input type='hidden' name='{0}' value='{1}' />", key, aData(key))
        Next

        sb.Append("</form>")
        sb.Append("</body>")
        sb.Append("</html>")

        aThis.Write(sb.ToString())

        aThis.End()
    End Sub

End Module

6

มีอะไรใหม่ใน ASP.Net 3.5 คือคุณสมบัติ "PostBackUrl" ของปุ่ม ASP คุณสามารถตั้งค่าเป็นที่อยู่ของเพจที่คุณต้องการโพสต์โดยตรงและเมื่อคลิกที่ปุ่มนั้นแทนที่จะโพสต์กลับไปที่หน้าเดียวกันเหมือนปกติมันจะโพสต์ไปยังหน้าที่คุณระบุไว้ มีประโยชน์ ตรวจสอบให้แน่ใจว่า UseSubmitBehavior ถูกตั้งค่าเป็น TRUE เช่นกัน


4

คิดว่าน่าสนใจที่จะแบ่งปันว่า heroku ทำสิ่งนี้กับ SSO แก่ผู้ให้บริการเสริม

ตัวอย่างของวิธีการทำงานสามารถเห็นได้ในแหล่งที่มากับเครื่องมือ "kensa":

https://github.com/heroku/kensa/blob/d4a56d50dcbebc2d26a4950081acda988937ee10/lib/heroku/kensa/post_proxy.rb

และสามารถเห็นได้ในทางปฏิบัติหากคุณเปิดจาวาสคริปต์ ตัวอย่างหน้าแหล่งที่มา:

<!DOCTYPE HTML>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Heroku Add-ons SSO</title>
  </head>

  <body>
    <form method="POST" action="https://XXXXXXXX/sso/login">

        <input type="hidden" name="email" value="XXXXXXXX" />

        <input type="hidden" name="app" value="XXXXXXXXXX" />

        <input type="hidden" name="id" value="XXXXXXXX" />

        <input type="hidden" name="timestamp" value="1382728968" />

        <input type="hidden" name="token" value="XXXXXXX" />

        <input type="hidden" name="nav-data" value="XXXXXXXXX" />

    </form>

    <script type="text/javascript">
      document.forms[0].submit();
    </script>
  </body>
</html>


2

@ Matt,

คุณยังคงสามารถใช้ HttpWebRequest จากนั้นสั่งการตอบสนองที่คุณได้รับกับการตอบกลับของสตรีมจริงซึ่งจะให้บริการการตอบกลับกลับไปยังผู้ใช้ ปัญหาเดียวก็คือว่า URL สัมพัทธ์ใด ๆ จะถูกทำลาย

ถึงกระนั้นนั่นก็อาจใช้ได้


2

นี่คือสิ่งที่ฉันจะทำ:

ใส่ข้อมูลในรูปแบบมาตรฐาน (โดยไม่มีแอตทริบิวต์ runat = "server") และตั้งค่าการกระทำของแบบฟอร์มเพื่อโพสต์ไปยังหน้าเว็บไซต์ภายนอกเป้าหมาย ก่อนที่จะส่งฉันจะส่งข้อมูลไปยังเซิร์ฟเวอร์ของฉันโดยใช้ XmlHttpRequestและวิเคราะห์การตอบสนอง หากคำตอบนั้นหมายความว่าคุณควรไปข้างหน้าด้วยการโพสต์นอกสถานที่แล้วฉัน (JavaScript) จะดำเนินการโพสต์ต่อไปมิฉะนั้นฉันจะเปลี่ยนเส้นทางไปยังหน้าบนเว็บไซต์ของฉัน


วิธีนี้ใช้ได้ผล แต่เป็นสิ่งสำคัญที่จะต้องทราบว่าคุณสูญเสียหน้าที่การใช้งานฝั่งเซิร์ฟเวอร์ ASP.NET ทั้งหมด
senfo

2

ใน PHP คุณสามารถส่งข้อมูล POST ด้วย cURL มีสิ่งที่เปรียบได้สำหรับ. NET?

ใช่ HttpWebRequest ดูโพสต์ของฉันด้านล่าง


2

ไม่ควรใช้เมธอด GET (และ HEAD) เพื่อทำสิ่งใดก็ตามที่มีผลข้างเคียง ผลข้างเคียงอาจกำลังอัปเดตสถานะของเว็บแอปพลิเคชันหรืออาจกำลังชาร์จบัตรเครดิตของคุณ หากการกระทำมีผลข้างเคียงวิธีอื่น (POST) ควรใช้แทน

ดังนั้นผู้ใช้ (หรือเบราว์เซอร์) จึงไม่ควรรับผิดชอบต่อสิ่งที่ GET ทำ หากผลข้างเคียงที่เป็นอันตรายหรือมีราคาแพงเกิดขึ้นเนื่องจาก GET นั่นอาจเป็นความผิดของแอปพลิเคชันเว็บไม่ใช่ผู้ใช้ ตามข้อมูลจำเพาะตัวแทนผู้ใช้จะต้องไม่ติดตามการเปลี่ยนเส้นทางโดยอัตโนมัติเว้นแต่จะเป็นการตอบกลับคำขอ GET หรือ HEAD

แน่นอนคำขอ GET จำนวนมากมีผลข้างเคียงบางอย่างแม้ว่าจะเป็นเพียงการผนวกเข้ากับไฟล์บันทึก สิ่งสำคัญคือแอปพลิเคชันไม่ใช่ผู้ใช้ควรรับผิดชอบต่อผลกระทบเหล่านั้น

ในส่วนที่เกี่ยวข้องของข้อมูลจำเพาะ HTTP เป็น9.1.1 และ 9.1.2และ10.3


1

ฉันขอแนะนำให้สร้าง HttpWebRequest เพื่อเรียกใช้ POST ของคุณโดยทางโปรแกรมแล้วเปลี่ยนเส้นทางหลังจากอ่านการตอบกลับหากทำได้


1

รหัสที่คัดลอกได้วางอยู่บนพื้นฐานของวิธีการของ Pavlo Neyman

RedirectPost (สตริง URL, T bodyPayload) และ GetPostData () สำหรับผู้ที่ต้องการถ่ายโอนข้อมูลที่พิมพ์ออกมาอย่างรุนแรงในหน้าแหล่งข้อมูลและดึงข้อมูลกลับมาที่เป้าหมายหนึ่ง ข้อมูลจะต้องเป็นอนุกรมโดย NewtonSoft Json.NET และคุณต้องอ้างอิงห้องสมุดแน่นอน

เพียงคัดลอกวางลงในหน้าของคุณหรือดีกว่า แต่คลาสพื้นฐานสำหรับหน้าของคุณและใช้ในทุกที่ในแอปพลิเคชันของคุณ

ใจของฉันออกไปทุกท่านที่ยังคงต้องใช้เว็บฟอร์มในปี 2019 ด้วยเหตุผลใดก็ตาม

        protected void RedirectPost(string url, IEnumerable<KeyValuePair<string,string>> fields)
        {
            Response.Clear();

            const string template =
@"<html>
<body onload='document.forms[""form""].submit()'>
<form name='form' action='{0}' method='post'>
{1}
</form>
</body>
</html>";

            var fieldsSection = string.Join(
                    Environment.NewLine,
                    fields.Select(x => $"<input type='hidden' name='{HttpUtility.UrlEncode(x.Key)}' value='{HttpUtility.UrlEncode(x.Value)}'>")
                );

            var html = string.Format(template, HttpUtility.UrlEncode(url), fieldsSection);

            Response.Write(html);

            Response.End();
        }

        private const string JsonDataFieldName = "_jsonData";

        protected void RedirectPost<T>(string url, T bodyPayload)
        {
            var json = JsonConvert.SerializeObject(bodyPayload, Formatting.Indented);
            //explicit type declaration to prevent recursion
            IEnumerable<KeyValuePair<string, string>> postFields = new List<KeyValuePair<string, string>>()
                {new KeyValuePair<string, string>(JsonDataFieldName, json)};

            RedirectPost(url, postFields);

        }

        protected T GetPostData<T>() where T: class 
        {
            var urlEncodedFieldData = Request.Params[JsonDataFieldName];
            if (string.IsNullOrEmpty(urlEncodedFieldData))
            {
                return null;// default(T);
            }

            var fieldData = HttpUtility.UrlDecode(urlEncodedFieldData);

            var result = JsonConvert.DeserializeObject<T>(fieldData);
            return result;
        }

0

โดยทั่วไปสิ่งที่คุณจะต้องมีคือดำเนินการบางสถานะระหว่างคำขอทั้งสองนี้ จริงๆแล้วมันมีวิธีที่ขี้ขลาดจริงๆในการทำเช่นนี้ซึ่งไม่ได้พึ่งพา JavaScript (คิดว่า <noscript />)

Set-Cookie: name=value; Max-Age=120; Path=/redirect.html

เมื่อมีคุกกี้นั้นคุณสามารถขอ /redirect.html เรียกข้อมูล name = value ต่อไปนี้เพื่อให้คุณสามารถเก็บข้อมูลประเภทใด ๆ ในสตริงคู่ชื่อ / ค่านี้สูงสุดถึง 4K ของข้อมูล (ขีด จำกัด คุกกี้ทั่วไป) แน่นอนคุณควรหลีกเลี่ยงสิ่งนี้และเก็บรหัสสถานะและค่าสถานะบิตแทน

เมื่อได้รับคำขอนี้คุณจะตอบกลับพร้อมกับลบคำขอสำหรับรหัสสถานะนั้น

Set-Cookie: name=value; Max-Age=0; Path=/redirect.html

HTTP ของฉันเป็นสนิมเล็กน้อยฉันได้รับราง RFC2109 และ RFC2965 เพื่อคิดว่าเชื่อถือได้จริงหรือไม่โดยเฉพาะฉันต้องการให้คุกกี้ไปกลับอย่างแน่นอนหนึ่งครั้ง แต่ดูเหมือนจะไม่เป็นไปได้เช่นกันคุกกี้ของบุคคลที่สาม อาจเป็นปัญหาสำหรับคุณหากคุณย้ายที่อยู่ไปยังโดเมนอื่น สิ่งนี้ยังคงเป็นไปได้ แต่ไม่เจ็บปวดเมื่อคุณทำสิ่งต่าง ๆ ภายในโดเมนของคุณเอง

ปัญหาที่นี่คือการเกิดขึ้นพร้อมกันถ้าผู้ใช้ระดับสูงกำลังใช้หลายแท็บและจัดการการแทรกสองคำขอที่อยู่ในเซสชั่นเดียวกัน (ซึ่งไม่น่าเป็นไปได้มาก แต่ไม่เป็นไปไม่ได้) สิ่งนี้อาจนำไปสู่

เป็น <noscript /> วิธีการปัดเศษ HTTP โดยไม่มี URL และ JavaScript ที่ไม่มีความหมาย

ฉันให้รหัสนี้เป็นแนวคิด: หากรหัสนี้ทำงานในบริบทที่คุณไม่คุ้นเคยกับฉันคิดว่าคุณสามารถทำงานได้ว่าส่วนใดเป็นอะไร

แนวคิดคือคุณโทรหาที่ตั้งใหม่ด้วยบางสถานะเมื่อคุณเปลี่ยนเส้นทางและ 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;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.