แนวทางที่ชัดเจนสำหรับการจัดการข้อผิดพลาดที่กำหนดเองใน ASP.NET MVC 3 มีอะไรบ้าง


44

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

นี่คือเป้าหมายของฉัน:

สำหรับข้อผิดพลาดเซิร์ฟเวอร์ / ข้อยกเว้น:

  1. แสดงข้อมูลการดีบักใน dev
  2. แสดงหน้าข้อผิดพลาดที่เป็นมิตรในการผลิต
  3. บันทึกข้อผิดพลาดและส่งอีเมลถึงผู้ดูแลระบบในการผลิต
  4. ส่งคืนรหัสสถานะ HTTP 500

สำหรับข้อผิดพลาด 404 ไม่พบ:

  1. แสดงหน้าข้อผิดพลาดที่เป็นมิตร
  2. บันทึกข้อผิดพลาดและส่งอีเมลถึงผู้ดูแลระบบในการผลิต
  3. ส่งคืนรหัสสถานะ HTTP 404

มีวิธีในการบรรลุเป้าหมายเหล่านี้ด้วย ASP.NET MVC หรือไม่?


2
ฉันต้องการให้คำถามนี้ถูกย้ายกลับเป็นดังนั้นเพื่อให้ได้คำตอบเพิ่มเติม ฉันกำลังหาคำตอบที่เข้ารหัส
Shawn Mclean

@Shawn ไม่น่าจะเกิดขึ้น คำถามมีมากขึ้นในหัวข้อที่นี่มากกว่าที่ SO และมีคำตอบที่ยอมรับ โดยทั่วไปคำถามจะไม่ได้รับการโยกย้ายอีกครั้งด้วยเหตุผลทางเทคนิค หากคุณต้องการความช่วยเหลือในการเข้ารหัสวิธีจัดการข้อผิดพลาดเฉพาะโปรดเปิดคำถามใหม่ใน StackOverflow มิฉะนั้น "คำตอบที่เข้ารหัส" อาจเป็นเกณฑ์ที่กว้างเกินไปที่จะเป็นประโยชน์หรือตอบได้ สุดท้าย แต่ไม่ท้ายสุดวิธีที่ดีที่สุดในการดึงดูดความสนใจของผู้ดูแลคำถามคือการติดธง ความคิดเห็นของคุณที่นี่มีแนวโน้มว่าจะไม่มีใครสังเกตเห็นหากไม่ได้ทำการตั้งค่าสถานะอัตโนมัติโดยการกดจำนวนความคิดเห็นมากกว่า 20
Adam Lear

เคยมีประมาณ 10 ความคิดเห็นที่นี่พวกเขาทั้งหมดไปไหน
RyanW

ฉันพบวิธีแก้ปัญหาที่ตรงกับเป้าหมายของคุณ ฉันมีมันเป็นคำตอบอื่นใน SO: stackoverflow.com/questions/6508415/ …
Jesse Webb

1
@ AnnaLear ฉันเห็นด้วยกับ Shawn ฉันพบหน้านี้ผ่านทาง Google เท่านั้น โปรดทราบว่าคำตอบเกือบทั้งหมดด้านล่างมีลิงค์กลับไปที่ Stack Overflow สำหรับฉันที่พูดถึงปริมาณในสิ่งที่ควรจะถูกทิ้งไว้ที่นั่นตั้งแต่แรก
รีเบคก้า

คำตอบ:


23

ฉันจะแบ่งปันวิธีที่ฉันลงเอยด้วยการทำเช่นนี้นั่นเป็นส่วนหนึ่งของคำถามเดิม

ครั้งแรกปัญหาที่ฉันพบ:

  1. ด้วย customErrors on (เช่นในการผลิต) HandleErrorแอตทริบิวต์ทั่วโลกจะกลืนข้อยกเว้นและแสดงมุมมองข้อผิดพลาดของคุณ แต่จากนั้นคุณไม่สามารถบันทึกด้วยเครื่องมือ addon เช่น elmah เนื่องจาก elmah ไม่เคยเห็น คุณสามารถบันทึกไว้ในมุมมองของคุณฉันคิดว่า แต่มันเป็นมุมมองที่ดูเหมือนว่าผิด แอตทริบิวต์ส่วนกลาง HandleError ปรากฏขึ้นใหม่ในเทมเพลตโครงการ MVC 3 RTM Visual Studio

  2. customErrors พร้อม URL สำหรับปลายทาง MVC จะส่งคืนรหัสสถานะ 302 มีคุณสมบัติการเปลี่ยนเส้นทาง แต่คุณไม่สามารถจับคู่ URL mvc ใน customErrors และใช้โหมด ResponseRewrite ( https://stackoverflow.com/questions/781861/customerrors-does-not-work-when-setting-redirectmode-responserewrite/3770265#3770265 )

  3. หลีกเลี่ยง customErrors อย่างสมบูรณ์และการจัดการทุกอย่างที่กำหนดเองในแอปของคุณนำไปสู่ความซับซ้อนมาก IMO (แก้ปัญหานี้: https://stackoverflow.com/questions/619895/how-can-i-properly-handle-404s-in-asp-net-mvc/2577095#2579595แต่ไม่เหมาะสำหรับโครงการของเรา)

ทางออกของฉัน

ฉันนำ MVC ออกจากสมการอย่างสมบูรณ์ ฉันได้ลบHandleErrorAttributeตัวกรองทั่วโลกใน global.asax และมุ่งเน้นไปที่การกำหนดค่า customErrors ทั้งหมดเปลี่ยนไปใช้การเปลี่ยนเส้นทาง WebForm และเปลี่ยนเป็นการเปลี่ยนเส้นทางResponseRewriteโหมดเป็นเพื่อหลีกเลี่ยงรหัสตอบสนอง 302 HTTP

<customErrors mode="On" defaultRedirect="/Error.aspx" redirectMode="ResponseRewrite">
  <error statusCode="404" redirect="/NotFound.aspx" />
</customErrors>

จากนั้นในNotFound.aspxเหตุการณ์ page_load ให้ตั้งค่าเป็นResponse.StatusCode404 และใน Error.aspx ให้ตั้งรหัส 500

ผล:

บรรลุเป้าหมายทั้งสองอย่างด้วยบันทึก Elmah หน้าข้อผิดพลาดที่เป็นมิตรและรหัสสถานะพร้อมรหัสบรรทัดหนึ่งบนโค้ด - หลัง เราไม่ได้ทำในสิ่งที่ "MVC Way" เหมือนที่ทำไว้ก่อนหน้านี้ แต่ฉันก็โอเคถ้ามันเป็นโค้ดสองบรรทัด


5

ฉันคิดว่า MVC, ASP และเฟรมเวิร์กการจัดการข้อยกเว้น / บันทึกที่คุณชื่นชอบสามารถจัดการกับเป้าหมายของคุณได้เป็นอย่างดี ทั้ง ELMAH และ Enterprise Library ให้การจัดการและการบันทึกที่ง่ายต่อการใช้ดังนั้นโปรดเลือกรายการโปรดของคุณ .. ฉันจะไม่เข้าไปดูข้อดีข้อเสียของแต่ละข้อที่นี่

หมายเหตุ: คุณไม่สามารถแสดงหน้าข้อผิดพลาดที่เป็นมิตรและส่งคืน HTTP 404 หรือ 500 ตามที่คำถามของคุณแนะนำ เมื่อคุณกลับหน้าข้อผิดพลาดที่จำง่ายรหัส HTTP ที่ส่งคืนไปยังเบราว์เซอร์ของคุณจะเป็น 302 นี่คือการเปลี่ยนเส้นทางไปยังหน้าข้อผิดพลาดที่เป็นมิตร

หน้าข้อผิดพลาดที่เป็นมิตร

ดูเหมือนว่าคุณจะสามารถบรรลุเป้าหมายของคุณได้ด้วยการตั้งค่า web.config ที่ดีซึ่งเป็นส่วนหนึ่งของ ASP.net มาระยะหนึ่ง คุณพูดถึงการแสดงข้อมูลการแก้ปัญหาเมื่อใน dev และแสดงหน้าเป็นมิตรในการผลิต คุณสามารถใช้ส่วนข้อผิดพลาดที่กำหนดเองของ web.config สำหรับสิ่งนี้ (ตั้งค่า CustomErrors = "Off" เพื่อแสดงข้อมูลการดีบัก) ฉันจะสมมติว่าคุณคุ้นเคยกับแอตทริบิวต์ CustomErrors หากไม่ได้อ่าน:

http://msdn.microsoft.com/en-us/library/h0hfz6fc.aspx

หากคุณต้องการความละเอียดที่มากกว่าในการควบคุมมุมมองข้อผิดพลาดที่คุณแสดงให้ใช้แอตทริบิวต์ HandleError ของ MVC วิธีนี้คุณสามารถเลือกมุมมองข้อผิดพลาดที่แตกต่างกันสำหรับแต่ละ Action / Controller

http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx

การบันทึกข้อยกเว้น

ดูเหมือนว่าคุณต้องการตอบสนองต่อข้อยกเว้นทั้งหมดของคุณในลักษณะเดียวกัน ('บันทึกข้อผิดพลาดและส่งอีเมลให้ผู้ดูแลระบบในการผลิต') หากเป็นกรณีนี้ตัวเลือกที่ง่ายที่สุดของคุณคือการเพิ่มรหัสไป

Application_Error (ผู้ส่งวัตถุ, EventArgs e)

ใน global.asax ของคุณ นี่คือที่ที่คุณสามารถส่งต่อไปยังเฟรมเวิร์กการบันทึกที่คุณเลือก

หากคุณต้องการควบคุมการบันทึก / จัดการข้อยกเว้นของคุณมากขึ้นคุณสามารถคลาสย่อย HandleErrorAttribute และแทนที่

OnException(System.Web.Mvc.ExceptionContext filterContext)

นี่เป็นอีกที่ที่คุณสามารถส่งต่อไปยังเฟรมเวิร์กการบันทึกที่คุณเลือก

https://stackoverflow.com/questions/183316/asp-net-mvc-handleerror

สิ่งนี้ทำให้คุณสามารถควบคุมได้มากกว่าเทคนิค Application_Error ที่กล่าวถึงข้างต้น

โดยทั่วไป MVC ช่วยให้คุณควบคุมการจัดการข้อผิดพลาดได้อย่างละเอียด หากคุณไม่ต้องการการควบคุมนี้คุณสามารถถอยกลับไปใช้วิธีการของ ASP.net ในการทำสิ่งต่าง ๆ เช่นการกำหนดหน้าข้อผิดพลาดบน web.config ของคุณ


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

ฉันต้องการแทนที่ OnException วิธีการเข้าสู่ระบบด้วยวิธีนี้ฉันรู้ว่าฉันสามารถบันทึกทุกอย่างแม้เกิดข้อผิดพลาดจากการโทร Ajaxซึ่งฉันค้นหาจะไม่เรียก Application_Error ของคุณ
อลิเซีย

@Alicia รหัสตัวอย่างแบบเต็ม?
Kiquenet
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.