สิ่งที่ทำให้เกิด "ความยาวไม่ถูกต้องสำหรับอาร์เรย์ถ่าน Base-64"


91

ฉันมีน้อยมากที่จะไปที่นี่ ฉันทำซ้ำสิ่งนี้ในเครื่องไม่ได้ แต่เมื่อผู้ใช้ได้รับข้อผิดพลาดฉันได้รับการแจ้งเตือนข้อยกเว้นอีเมลอัตโนมัติ:

Invalid length for a Base-64 char array.

  at System.Convert.FromBase64String(String s)
  at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
  at System.Web.UI.ObjectStateFormatter.System.Web.UI.IStateFormatter.Deserialize(String serializedState)
  at System.Web.UI.Util.DeserializeWithAssert(IStateFormatter formatter, String serializedState)
  at System.Web.UI.HiddenFieldPageStatePersister.Load()

ฉันมีแนวโน้มที่จะคิดว่ามีปัญหากับข้อมูลที่ถูกกำหนดให้กับ viewstate ตัวอย่างเช่น:

List<int> SelectedActionIDList = GetSelectedActionIDList();
ViewState["_SelectedActionIDList"] = SelectedActionIDList;

เป็นการยากที่จะคาดเดาแหล่งที่มาของข้อผิดพลาดโดยที่ไม่สามารถสร้างข้อผิดพลาดซ้ำในเครื่องได้

หากใครเคยมีประสบการณ์เกี่ยวกับข้อผิดพลาดนี้ฉันอยากจะรู้ว่าคุณพบอะไร

คำตอบ:


36

ฉันเห็นข้อผิดพลาดนี้เกิดจากการรวมกันของวิวสเตทที่มีขนาดดีและอุปกรณ์ / ไฟร์วอลล์กรองเนื้อหาที่ก้าวร้าว (โดยเฉพาะเมื่อต้องติดต่อกับสถาบันการศึกษาระดับ K-12)

เราแก้ไขปัญหานี้ด้วยการจัดเก็บ Viewstate ใน SQL Server ก่อนที่จะไปเส้นทางนั้นฉันขอแนะนำให้พยายาม จำกัด การใช้งาน viewstate ของคุณโดยไม่เก็บสิ่งที่มีขนาดใหญ่ไว้ในนั้นและปิดการควบคุมทั้งหมดที่ไม่จำเป็นต้องใช้

การอ้างอิงสำหรับการจัดเก็บ ViewState ใน SQL Server:
MSDN - ภาพรวมของ PageStatePersister
ASP Alliance - วิธีง่ายๆในการจัดเก็บ viewstate ใน SQL Server
Code Project - ViewState Provider Model


ฉันคัดลอกขอบเขตของหน้าและวางลงใน Word มีความยาวมากกว่า 86,000 อักขระ ดูเหมือนว่าจะมากเกินไป
สลิม

ใช่ตอนนี้ฉันกำลังประสบปัญหา ฉันได้ปิด ViewState สำหรับการควบคุมทั้งหมดที่ฉันสามารถทำได้ ฉันใช้ตัวควบคุมวิซาร์ดกับหลาย ๆ เพจและเนื้อหามากมาย คำแนะนำใด ๆ?
Mike Cole

@ ไมค์ซีนี่เป็นปัญหาที่น่าหงุดหงิดมาก! คุณสามารถแบ่งเนื้อหาของแต่ละหน้าของตัวช่วยสร้างเป็นการควบคุมผู้ใช้และโหลดเนื้อหาตามต้องการ (ผ่าน ajax?) แน่นอนว่านี่เป็นเพียงวิธีแก้ปัญหาสำหรับหน้าเดียวเท่านั้นหากคุณเริ่มประสบปัญหาอย่างสม่ำเสมอคุณอาจต้องพิจารณาเก็บ viewstate ไว้ในฐานข้อมูลของคุณ ฉันได้อัปเดตคำตอบของฉันด้วยข้อมูลอ้างอิงสำหรับการจัดเก็บ viewstate ใน SQL Server
Jimmie R. Houts

1
ปัญหาอีกประการหนึ่งที่ฉันพบกับความยาวมากกว่า 86,000 ตัวอักษร (จริงๆแล้วอาจใกล้ถึง 85K ฉันคิดว่าสมมติว่าเป็นอักขระไบต์เดียว) ก็คือแอป. NET ของคุณอาจเริ่มวางสตริง viewstate บนฮีปวัตถุขนาดใหญ่ซึ่งอาจนำไปสู่การฮีป การแยกส่วนเมื่อเวลาผ่านไป (และในที่สุด OutOfMemoryException) หากพูลแอปไม่ถูกรีไซเคิล
nothingisnecessary

ฉันประสบปัญหาเดียวกันวิธีแก้ไขปัญหานี้โปรดชี้แจง
Sajith

84

หลังจาก urlDecode ประมวลผลข้อความมันจะแทนที่ตัวอักษร '+' ทั้งหมดด้วย '' ... ดังนั้นข้อผิดพลาด คุณควรเรียกคำสั่งนี้เพื่อทำให้ฐาน 64 เข้ากันได้อีกครั้ง:

        sEncryptedString = sEncryptedString.Replace(' ', '+');

สิ่งที่ยอดเยี่ยม ขอบคุณ. ฉันกำลังเรียกใช้บริการเว็บ ASP.NET จากแอปพลิเคชัน C ++ MFC และอาจแตกแขนงออกไปในหลายทิศทางเพื่อพยายามแก้ไขปัญหานี้และหลังจากใช้เวลาสองสามชั่วโมงไปแล้ว คุณช่วยฉันประหยัดเวลาได้มาก
nspire

3
เพียงแค่แก้ไขปัญหานี้และอย่างที่คุณบอกว่าเป็นช่องว่างแทนที่ด้วยการ+แก้ไข ฮีโร่!
mattytommo

ใครสามารถให้คำแนะนำเกี่ยวกับตำแหน่งที่จะรวมรหัสนี้? ฉันกำลังเผชิญกับปัญหานี้บ่อยครั้ง แต่จากข้อมูลโค้ดฉันไม่สามารถระบุได้ว่าจะดำเนินการแก้ไขที่ใด
dst3p

@ dst3p ใช้ที่ใดก็ได้ในไปป์ไลน์การประมวลผลที่คุณพบข้อผิดพลาด ตรวจสอบการติดตามสแต็กของคุณและดูว่าวิธีใดทำให้เกิดข้อผิดพลาด
Jalal El-Shaer

21

ฉันเดาว่ามีบางอย่างเข้ารหัสหรือถอดรหัสบ่อยเกินไปหรือคุณมีข้อความหลายบรรทัด

สตริง Base64 ต้องมีความยาวหลายอักขระ 4 ตัว - ทุกๆ 4 อักขระแทนข้อมูลอินพุต 3 ไบต์ อย่างไรก็ตามข้อมูลสถานะมุมมองที่ส่งกลับโดย ASP.NET นั้นเสียหาย - ความยาวไม่ใช่ผลคูณของ 4

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


ในกรณีของฉันเบราว์เซอร์จะเป็น Safari เสมอไม่ว่าจะเป็นเวอร์ชันมือถือหรือเดสก์ท็อป
cockypup

12

ลองสิ่งนี้:

public string EncodeBase64(string data)
{
    string s = data.Trim().Replace(" ", "+");
    if (s.Length % 4 > 0)
        s = s.PadRight(s.Length + 4 - s.Length % 4, '=');
    return Encoding.UTF8.GetString(Convert.FromBase64String(s));
}

วิธีนี้ช่วยแก้ไขปัญหา แม้ว่าฉันไม่ได้ใช้การเข้ารหัส UTF8
Abhishek Shrivastava


8

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

ASP.NET 2.0 เปิดตัวกลไก ViewState Chunkingซึ่งแบ่ง ViewState ออกเป็นส่วนที่จัดการได้ทำให้ ViewState สามารถส่งผ่านพร็อกซี / ไฟร์วอลล์ได้โดยไม่มีปัญหา

หากต้องการเปิดใช้งานคุณสมบัตินี้เพียงแค่เพิ่มบรรทัดต่อไปนี้ในไฟล์ web.config ของคุณ

<pages maxPageStateFieldLength="4000">

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


สิ่งนี้อาจมีผลข้างเคียงหรือไม่?
MonsterMMORPG


แล้วความยาวที่ดีที่สุดของคุณคืออะไร? ฉันตั้งไว้ 1024
MonsterMMORPG

1

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

ในกรณีของฉันมันเป็นปัญหา localhost แต่เพียงผู้เดียวบนเครื่อง dev ของฉันที่มี DB ของแอปด้วย มันเป็นแอพ. NET 2.0 ที่ฉันกำลังแก้ไขด้วย VS2005 เครื่อง Win7 64 บิตยังติดตั้ง VS2008 และ. NET 3.5

นี่คือสิ่งที่จะสร้างข้อผิดพลาดจากรูปแบบต่างๆ:

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

ความล่าช้าหนึ่งหรือสองนาที "กำลังรอ localhost" จากนั้นเบราว์เซอร์ "รีเซ็ตการเชื่อมต่อ" และglobal.asaxบันทึกการดักจับข้อผิดพลาดของแอปพลิเคชัน

Application_Error event: Invalid length for a Base-64 char array.
Stack Trace:
     at System.Convert.FromBase64String(String s)
     at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
     at System.Web.UI.Util.DeserializeWithAssert(IStateFormatter formatter, String serializedState)
     at System.Web.UI.HiddenFieldPageStatePersister.Load()

ในกรณีนี้ไม่ใช่ SIZE ของ viewstate แต่เป็นสิ่งที่เกี่ยวข้องกับการแคชเพจและ / หรือ viewstate ที่ดูเหมือนจะกัดฉัน การตั้งค่า<pages>พารามิเตอร์enableEventValidation="false"และviewStateEncryption="Never"ในWeb.configไม่ได้เปลี่ยนพฤติกรรม ไม่ได้ตั้งค่าเป็นmaxPageStateFieldLengthสิ่งที่เรียบง่าย


1

ลองดูที่ HttpHandlers ของคุณ ฉันสังเกตเห็นข้อผิดพลาดแปลก ๆ และสุ่มอย่างสมบูรณ์ในช่วงสองสามเดือนที่ผ่านมาหลังจากที่ฉันใช้เครื่องมือบีบอัด (RadCompression จาก Telerik) ฉันสังเกตเห็นข้อผิดพลาดเช่น:

  • System.Web.HttpException: ไม่สามารถตรวจสอบข้อมูลได้

  • System.Web.HttpException: ไคลเอนต์ตัดการเชื่อมต่อ -> System.Web.UI.ViewStateException: viewstate ไม่ถูกต้อง

และ

  • System.FormatException: ความยาวไม่ถูกต้องสำหรับอาร์เรย์ถ่าน Base-64

  • System.Web.HttpException: ไคลเอนต์ตัดการเชื่อมต่อ ---> System.Web.UI.ViewStateException: viewstate ไม่ถูกต้อง

ฉันเขียนเกี่ยวกับเรื่องนี้ในบล็อกของฉัน


บล็อกของคุณไม่ทำงาน คุณมีลิงค์อื่นหรือโพสต์ข้อมูลที่เกี่ยวข้องได้ไหม thx
mga911


0

นี่เป็นเพราะสถานะการดูที่มากในกรณีของฉันฉันโชคดีเพราะฉันไม่ได้ใช้ viewstate ฉันเพิ่งเพิ่มenableviewstate="false"ในแท็กแบบฟอร์มและสถานะการดูเปลี่ยนจาก 35k เป็น 100 ตัวอักษร


0

ในระหว่างการทดสอบครั้งแรกสำหรับ Membership.ValidateUser กับ SqlMembershipProvider ฉันใช้อัลกอริทึมแฮช (SHA1) ร่วมกับเกลือและถ้าฉันเปลี่ยนความยาวของเกลือเป็นความยาวที่หารด้วยสี่ไม่ได้ฉันได้รับข้อผิดพลาดนี้

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


0

ดังที่ Jon Skeet กล่าวว่าสตริงต้องมีหลาย 4 ไบต์ แต่ฉันยังคงได้รับข้อผิดพลาด

อย่างน้อยก็ถูกลบออกในโหมดดีบัก กำหนดจุดพักConvert.FromBase64String()แล้วก้าวผ่านรหัส ข้อผิดพลาดหายไปอย่างน่าอัศจรรย์สำหรับฉัน :) อาจเกี่ยวข้องกับสถานะการดูและปัญหาอื่น ๆ ที่คล้ายกันตามที่คนอื่นรายงาน


0

นอกจากโซลูชันของ @ jalchrที่ช่วยฉันแล้วฉันยังพบว่าเมื่อโทรATL::Base64Encodeจากแอปพลิเคชัน c ++ เพื่อเข้ารหัสเนื้อหาที่คุณส่งผ่านไปยังบริการเว็บ ASP.NET คุณต้องมีอย่างอื่นด้วย นอกจาก

sEncryptedString = sEncryptedString.Replace(' ', '+'); 

จากการแก้ปัญหา @ jalchr ของคุณยังต้องให้แน่ใจว่าคุณไม่ได้ใช้ATL_BASE64_FLAG_NOPADธงATL::Base64Encode:

 BOOL bEncoded = Base64Encode(lpBuffer,
                    nBufferSizeInBytes,
                    strBase64Encoded.GetBufferSetLength(base64Length),
                    &base64Length,ATL_BASE64_FLAG_NOCRLF/*|ATL_BASE64_FLAG_NOPAD*/);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.