จากประสบการณ์ส่วนตัวของฉันในการใช้ ASP.NET และจากการค้นหาบนอินเทอร์เน็ต ฉันพบว่าวิธี ResolveUrl ของเพจทำให้เราเกิดปัญหาร้ายแรง
ปัญหาที่พบบ่อยที่สุดคือไม่สามารถใช้นอกขอบเขตของเพจหรือตัวควบคุมได้
ปัญหาอื่นๆ ทั้งหมดคือข้อบกพร่อง ตัวอย่างเช่น ไม่สามารถจัดการบาง URL ที่คุณให้ได้อย่างถูกต้อง ตัวอย่างเช่น ลอง Page.ResolveUrl("~/test.aspx?param=http://www.test.com") ผลลัพธ์จะเหมือนกับสตริงที่คุณป้อนโดยไม่มีการเปลี่ยนแปลงใดๆ การใช้ Reflector เพื่อดูโค้ด asp.net ฉันพบว่ากลไกในการแปลง URL ที่เกี่ยวข้องเป็น URL ที่สมบูรณ์จะค้นหา "://" ในสตริงเป็นอันดับแรก และหากพบจะส่งคืนโดยตรง ดังนั้น หากคุณส่งพารามิเตอร์ด้วย :// สตริงการสืบค้นก็จะถือว่าใช้ได้ เราทุกคนรู้ดีว่าพารามิเตอร์สตริงการสืบค้นควรได้รับการเข้ารหัส urlencode แต่หากไม่เป็นเช่นนั้น ก็ควรจะยอมรับได้สำหรับ URL อย่างจริงจัง ตรวจสอบเบราว์เซอร์ของคุณ
แนวทางออนไลน์ที่แนะนำคือการใช้ VirtualPathUtility.ToAbsolute ซึ่งค่อนข้างดีและสะดวกหากคุณส่ง URL เป็นสตริงการสืบค้น...ไม่เช่นนั้น ข้อยกเว้นจะเกิดขึ้น หากเป็น URL แบบเต็ม ก็จะส่งข้อยกเว้นด้วย!
ดังนั้นฉันจึงตัดสินใจหาวิธีแก้ปัญหาขั้นสุดท้าย
อันดับแรก ฉันกำลังมองหาตัวแปรที่ดีที่จะให้เส้นทางเสมือนแก่เราในขณะที่แอปพลิเคชันกำลังทำงานอยู่ โดยไม่ต้องใช้บริบทของหน้า
ฉันใช้ HttpRuntime.AppDomainAppVirtualPath สามารถใช้ได้ทุกที่ - แม้ในเวลาโทรกลับตามตัวจับเวลา! ไม่มีเครื่องหมายสแลชต่อท้ายในเส้นทาง ASP.NET ได้กำจัดเครื่องหมายทับอย่างแปลกประหลาด แต่เราสามารถแก้ไขได้ :-)
จากนั้น ฉันทำการทดสอบโดยใช้โค้ด ResolveUrl ดั้งเดิม และพบวิธีแทนที่ด้วย AppVirtualPath:
1. เมื่อ URL ขึ้นต้นด้วยเครื่องหมายทับ (/ หรือ ) จะไม่มีการเปลี่ยนแปลง!
2. เมื่อ URL ขึ้นต้นด้วย 〜/ จะถูกแทนที่ด้วย AppVirtualPath
3. เมื่อ URL เป็น URL ที่สมบูรณ์ จะไม่มีการเปลี่ยนแปลง
4. ในกรณีอื่นใด (แม้จะขึ้นต้นด้วย 〜 แทนที่จะเป็นเครื่องหมายทับ) URL จะถูกผนวกเข้ากับ AppVirtualPath
5. เมื่อใดก็ตามที่แก้ไข URL ก็จะแก้ไขเครื่องหมายทับด้วย ลบเครื่องหมายทับคู่ออกแล้วแทนที่ ด้วย /
รหัส:
รหัส
สตริงคงที่สาธารณะ ResolveUrl (สตริงสัมพันธ์Url)
-
ถ้า (relativeUrl == null) โยน ArgumentNullException ใหม่ ("relativeUrl");
ถ้า (relativeUrl.Length == 0 || ญาติUrl[0] == '/' ||
RelativeUrl[0] == '\') กลับ RelativeUrl;
int idxOfScheme =
สัมพันธ์Url.IndexOf(@"://", StringComparison.Ordinal);
ถ้า (idxOfScheme != -1)
-
int idxOfQM = สัมพันธ์Url.IndexOf('?');
ถ้า (idxOfQM == -1 || idxOfQM > idxOfScheme) ส่งคืน RelativeUrl;
-
StringBuilder sbUrl = ใหม่ StringBuilder();
sbUrl.ผนวก(HttpRuntime.AppDomainAppVirtualPath);
ถ้า (sbUrl.Length == 0 || sbUrl[sbUrl.Length - 1] != '/') sbUrl.Append('/');
// พบเครื่องหมายคำถามแล้วหรือยัง?
บูล foundQM = เท็จ;
bool foundSlash; // อักขระล่าสุดคือเครื่องหมายทับ?
ถ้า (relativeUrl.Length > 1
&& สัมพันธ์Url[0] == '~'
&& (relativeUrl[1] == '/' || ญาติUrl[1] == '\'))
-
สัมพันธ์Url = สัมพันธ์Url.สตริงย่อย(2);
พบ Slash = จริง;
-
อย่างอื่นที่พบ Slash = false;
foreach (ถ่าน c ในrelativeUrl)
-
ถ้า (!foundQM)
-
ถ้า (c == '?') พบ QM = true;
อื่น
-
ถ้า (c == '/' || c == '\')
-
ถ้า (foundSlash) ดำเนินการต่อ;
อื่น
-
sbUrl.ผนวก('/');
พบ Slash = จริง;
ดำเนินการต่อ;
-
-
อย่างอื่นถ้า (foundSlash) foundSlash = false;
-
-
sbUrl.ผนวก(c);
-
กลับ sbUrl.ToString();
-
หลังจากกรอกโค้ดเสร็จแล้วและเปรียบเทียบการทดสอบ ResolveUrl ดั้งเดิมซ้ำแล้วซ้ำเล่า ฉันก็เริ่มทดสอบประสิทธิภาพ... ในกรณีส่วนใหญ่ โค้ดของฉันทำงานได้เร็วกว่า ResolveUrl ดั้งเดิมถึง 2.7 เท่า! ฉันยังทดสอบมันแบบวนซ้ำ โดยรันโค้ด 100,000 ครั้งด้วย URL ที่แตกต่างกัน
อ้างอิงข้อความต้นฉบับ: http://www.codeproject.com/KB/aspnet/resolveurl.aspx
ผู้แต่ง: Zhu Qilin ที่มา: http://zhuqil.cnblogs.com
ลิขสิทธิ์ของบทความนี้เป็นของผู้เขียนและ Blog Park อย่างไรก็ตาม จะต้องคงข้อความนี้ไว้โดยไม่ได้รับความยินยอมจากผู้เขียน และต้องระบุลิงก์ไปยังข้อความต้นฉบับในตำแหน่งที่ชัดเจนในหน้าบทความ สงวนสิทธิ์ในการดำเนินการรับผิดทางกฎหมาย