Apa panduan definitif untuk Penanganan Kesalahan kustom di ASP.NET MVC 3?

44

Proses melakukan penanganan kesalahan kustom di ASP.NET MVC (3 dalam kasus ini) tampaknya sangat diabaikan. Saya telah membaca berbagai pertanyaan dan jawaban di sini, di web, halaman bantuan untuk berbagai alat (seperti Elmah), tetapi saya merasa seperti saya telah berada dalam lingkaran yang lengkap dan masih belum memiliki solusi terbaik. Dengan bantuan Anda, mungkin kami dapat menetapkan pendekatan standar baru untuk penanganan kesalahan. Saya ingin menjaga hal-hal sederhana dan tidak over-engineer ini.

Inilah tujuan saya:

Untuk kesalahan / pengecualian Server:

  1. Tampilkan informasi debug di dev
  2. Tampilkan halaman kesalahan ramah dalam produksi
  3. Catat kesalahan dan kirimkan melalui email ke administrator dalam produksi
  4. Kembalikan 500 Kode Status HTTP

Untuk 404 Tidak Ditemukan kesalahan:

  1. Tampilkan halaman kesalahan ramah
  2. Catat kesalahan dan kirimkan melalui email ke administrator dalam produksi
  3. Kembalikan 404 Kode Status HTTP

Apakah ada cara untuk memenuhi tujuan ini dengan ASP.NET MVC?

RyanW
sumber
2
Saya ingin pertanyaan ini dimigrasi KEMBALI ke SO sehingga dapat memperoleh lebih banyak jawaban. Saya mencari jawaban kode.
Shawn Mclean
@ Shawn Itu tidak mungkin terjadi. Pertanyaannya lebih pada topik di sini daripada di SO dan memiliki jawaban yang diterima. Pertanyaan juga umumnya tidak dimigrasi ulang karena alasan teknis. Jika Anda memerlukan bantuan dengan pengkodean pendekatan penanganan kesalahan tertentu, silakan buka pertanyaan baru tentang StackOverflow. Kalau tidak, "jawaban yang dikodekan" mungkin terlalu luas kriteria untuk menjadi berguna atau tidak dapat dijawab. Last but not least, cara terbaik untuk menarik perhatian moderator ke sebuah pertanyaan adalah menandainya. Komentar Anda di sini kemungkinan besar tidak akan diperhatikan jika tidak melewati bendera otomatis dengan mendorong jumlah komentar lebih dari 20.
Adam Lear
Dulu ada sekitar 10 komentar di sini, kemana mereka semua pergi?
RyanW
Saya menemukan solusi yang memenuhi tujuan Anda. Saya memilikinya sebagai jawaban lain pada SO: stackoverflow.com/questions/6508415/...
Jesse Webb
1
@AnnaLear Saya setuju dengan Shawn. Saya hanya menemukan halaman ini melalui Google. Perhatikan bahwa hampir semua jawaban di bawah ini berisi tautan KEMBALI ke Stack Overflow. Bagi saya yang berbicara banyak, itu seharusnya dibiarkan di sana di tempat pertama.
Rebecca

Jawaban:

23

Saya akan membagikan cara saya akhirnya melakukan ini, itu adalah bagian dari pertanyaan awal.

Pertama, masalah yang saya temui:

  1. Dengan customErrors pada (yaitu dalam produksi) HandleErroratribut global menelan pengecualian dan membuat tampilan kesalahan Anda, tetapi kemudian Anda tidak dapat login dengan alat addon seperti elmah, karena elmah tidak pernah melihatnya. Anda bisa mencatatnya dalam pandangan Anda saya kira, tapi itu adalah pandangan, yang tampaknya salah. Atribut HandleError global muncul baru di templat proyek MVC 3 RTM Visual Studio.

  2. customErrors dengan url untuk titik akhir MVC menghasilkan 302 kode status. Ada properti redirectmode, tetapi Anda tidak dapat mencocokkan URL mvc di customErrors dan menggunakan mode ResponseRewrite. ( https://stackoverflow.com/questions/781861/customerrors-does-not-work-when-setting-redirectmode-responserewrite/3770265#3770265 )

  3. Menghindari customErrors sepenuhnya dan menangani semua kustom di aplikasi Anda menyebabkan banyak kompleksitas, IMO. (Saya suka ini: https://stackoverflow.com/questions/619895/how-can-i-properly-handle-404s-in-asp-net-mvc/2577095#2577095 , tapi itu tidak cocok untuk proyek kami)

Solusi saya

Saya telah mengambil MVC sepenuhnya dari persamaan. Saya telah menghapus HandleErrorAttributefilter global di global.asax dan fokus sepenuhnya pada konfigurasi customErrors, menggesernya untuk menggunakan pengalihan WebForm dan mengubah ke redirectmode ResponseRewriteuntuk menghindari 302 kode respons HTTP.

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

Kemudian, dalam NotFound.aspxevent page_load, atur Response.StatusCodeke 404 dan di Error.aspx atur kode 500.

Hasil:

Sasaran untuk keduanya telah dicapai dengan log Elmah, halaman kesalahan ramah, dan kode status dengan satu baris kode pada kode di belakang. Kami tidak melakukannya dengan "MVC Way" seperti solusi sebelumnya, tapi saya setuju dengan itu jika dua baris kode.

RyanW
sumber
5

Saya pikir MVC, ASP, dan kerangka penanganan logging / pengecualian favorit Anda dapat menangani tujuan Anda dengan cukup baik. ELMAH dan Enterprise Library keduanya menyediakan penanganan pengecualian dan pencatatan yang mudah digunakan, jadi pilihlah favorit Anda .. Saya tidak akan membahas pro dan kontra dari masing-masing di sini.

CATATAN: Anda tidak dapat menampilkan halaman kesalahan yang ramah DAN mengembalikan HTTP 404 atau 500 seperti yang disarankan pertanyaan Anda. Saat Anda mengembalikan halaman kesalahan ramah, kode HTTP yang dikembalikan ke browser Anda adalah 302. Ini adalah pengalihan ke halaman kesalahan ramah.

Halaman Kesalahan Ramah

Sepertinya Anda dapat mencapai tujuan Anda dengan pengaturan web.config yang bagus yang telah menjadi bagian dari ASP.net selama beberapa waktu. Anda menyebutkan menunjukkan informasi debug ketika di dev dan menampilkan halaman ramah dalam produksi. Anda dapat menggunakan bagian kesalahan khusus web.config untuk ini (Setel CustomErrors = "Off" untuk menampilkan informasi debug). Saya akan menganggap bahwa Anda terbiasa dengan atribut CustomErrors, jika tidak membaca ini:

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

Jika Anda memerlukan granularity kontrol yang lebih besar atas tampilan kesalahan yang Anda tampilkan, maka gunakan HandleError Attribute MVC. Dengan cara ini Anda dapat memilih tampilan kesalahan yang berbeda untuk setiap Tindakan / Pengendali.

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

Log Pengecualian

Sepertinya Anda ingin menanggapi semua pengecualian Anda dengan cara yang sama ('Kesalahan log dan kirim ke administrator dalam produksi'). Jika demikian, opsi paling sederhana Anda adalah menambahkan kode

Application_Error (pengirim objek, EventArgs e)

di global.asax Anda. Di sinilah Anda bisa menyampaikan kerangka logging yang Anda pilih.

Jika Anda ingin kontrol lebih besar atas penebangan / penanganan pengecualian Anda, maka Anda dapat mensubklasifikasikan HandleErrorAttribute dan menimpanya

OnException(System.Web.Mvc.ExceptionContext filterContext)

ini adalah tempat lain di mana Anda bisa menyampaikan kerangka penebangan yang Anda pilih.

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

Ini memberi Anda lebih banyak kontrol daripada teknik Application_Error yang disebutkan di atas.

Secara umum, MVC memberi Anda kendali besar tentang cara menangani kesalahan. Jika Anda tidak memerlukan kontrol ini maka Anda dapat kembali ke ASP.net cara melakukan hal-hal seperti mendefinisikan halaman kesalahan di web.config Anda.

nixon
sumber
Terima kasih banyak telah menambahkan pemikiran Anda. Saya pikir kode status 302 adalah pilihan desain yang buruk oleh tim ASP.NET asli. Saya akan membahasnya dalam jawaban saya juga, ada beberapa opsi untuk melakukan itu. Tampaknya beberapa di dunia MVC benar-benar mengabaikan customErrors dan menangani semuanya di aplikasi untuk dapat digunakan kembali lebih baik dan lebih banyak kontrol saat Anda tunjukkan. Tetapi, saya memiliki keberhasilan yang terbatas dalam mengimplementasikannya dan menambahkan banyak kode yang sepertinya lebih baik dibuat. Lebih banyak jawaban saya di bawah ini.
Saya lebih suka menimpa metode OnException untuk login, dengan cara ini saya tahu saya bisa mencatat semuanya, bahkan kesalahan terjadi dari panggilan Ajax yang saya temukan tidak akan memicu Application_Error Anda.
Alicia
@Alicia kode sampel lengkap?
Kiquenet