.NET: Pengecualian Yang Harus Dilempar Saat Pengaturan Konfigurasi yang Diperlukan Hilang?

123

Berikut skenario standar:

if(string.IsNullOrEmpty(Configuration.AppSettings["foobar"]))
   throw new SomeStandardException("Application not configured correctly, bozo.");

Masalahnya adalah, saya tidak sepenuhnya yakin pengecualian mana yangSomeStandardException seharusnya.

Saya meneliti Kerangka 3.5 dan menemukan dua kandidat yang mungkin: ConfigurationExceptiondan ConfigurationErrorsException.

System.Configuration.ConfigurationException

Pengecualian yang muncul ketika kesalahan sistem konfigurasi telah terjadi.

Catatan

The ConfigurationExceptioneksepsi dilemparkan jika upaya aplikasi untuk membaca atau menulis data ke file konfigurasi tapi tidak berhasil. Beberapa kemungkinan alasan untuk hal ini dapat mencakup format XML yang salah di file konfigurasi, masalah izin file, dan properti konfigurasi dengan nilai yang tidak valid.

catatan:

The ConfigurationExceptionobjek dipertahankan untuk kompatibilitas. The ConfigurationErrorsException objek menggantikannya untuk sistem konfigurasi.

Pengecualian ini sebenarnya terdengar sempurna untuk apa yang saya butuhkan, tapi sudah ditandai usang, jadi, ixnay on atthay.

Ini membawa kita ke hal yang sangat membingungkan ConfigurationErrorsException:

System.Configuration.ConfigurationErrorsException

Nilai saat ini bukan salah satu nilai EnableSessionState.

Seperti yang Anda lihat, dokumentasinya sama sekali tidak berguna. (Begitulah dalam bantuan lokal dan online.) Pemeriksaan kelas itu sendiri menunjukkan bahwa itu berlebihan secara drastis untuk apa yang saya inginkan.

Singkatnya, saya memerlukan pengecualian standar yang harus dibuang ketika pengaturan konfigurasi aplikasi hilang atau berisi nilai yang tidak valid. Anda akan berpikir Kerangka memiliki pengecualian seperti itu yang dimasukkan ke dalamnya untuk digunakan aplikasi. (Tampaknya memang demikian, tetapi ditandai usang, dan digantikan oleh sesuatu yang jauh lebih besar cakupannya.)

Solusi apa, jika ada, yang kalian gunakan untuk ini, dan apakah saya harus menyedotnya dan menggulung pengecualian saya sendiri untuk ini?

Edit Adenda

Beberapa orang bertanya apakah saya dapat memberikan nilai default atau tidak, dan melanjutkan. Dalam kasus tertentu, ya, dan dalam kasus tersebut, pengecualian tidak akan dilemparkan. Namun, untuk pengaturan tertentu, ini tidak berlaku. Misalnya: nama dan kredensial server database, server otentikasi, dan jalur ke aplikasi pihak ketiga yang diinstal.

Perlu juga dicatat bahwa aplikasi yang terutama saya kerjakan adalah aplikasi konsol yang berjalan dalam mode batch, dan saya ingin aplikasi tersebut menampilkan pengecualian yang ditangkap oleh metode utama dan dicatat dengan tepat jika hal tersebut tidak dikonfigurasi dengan benar. (Ini kode warisan yang saya warisi, dan saat ini hanya menganggap semuanya bagus.)

Mike Hofer
sumber
1
Dokumentasi untuk System.Configuration.ConfigurationErrorsException telah diperbarui.
slolife

Jawaban:

36

Anda tidak dibatasi dalam memberikan pengecualian pada pengecualian yang ada dalam Kerangka. Jika Anda memutuskan untuk menggunakan pengecualian yang ada, Anda tidak harus benar-benar mengikuti dokumentasi ke surat itu. Dokumentasi akan menjelaskan bagaimana framework menggunakan pengecualian tertentu, tetapi tidak menyiratkan batasan apa pun tentang cara Anda memilih untuk menggunakan / menggunakan kembali pengecualian yang ada.

Ini adalah aplikasi Anda - selama Anda mendokumentasikannya dan dengan jelas menunjukkan pengecualian yang akan dilemparkan dalam kasus tertentu dari nilai konfigurasi yang hilang, Anda dapat menggunakan pengecualian apa pun yang Anda suka. Jika Anda memang menginginkan indikasi yang sangat spesifik dari nilai yang hilang , Anda dapat mempertimbangkan untuk menulis pengecualian ConfigurationSettingMissing Anda sendiri:

[Serializable]
public class ConfigurationMissingException : ConfigurationErrorsException
{}

EDIT: Menulis pengecualian Anda sendiri dalam hal ini membawa manfaat tambahan untuk menjamin bahwa tidak akan pernah ada kebingungan mengenai dari mana pengecualian itu berasal- kerangka kerja, atau aplikasi Anda. Kerangka tidak akan pernah memberikan pengecualian khusus Anda.

UPDATE: Saya setuju dengan komentar, jadi saya telah mengubah subclass menjadi ConfigurationErrorsException dari Exception. Saya pikir itu umumnya ide yang baik untuk pengecualian kustom subclass dari pengecualian Framework yang ada jika memungkinkan, menghindari kelas Exception kecuali Anda memerlukan pengecualian khusus aplikasi.

Dave Swersky
sumber
17
Saya agak tidak setuju. Jika Anda akan menggunakan pengecualian yang sudah ada, itu harus digunakan PERSIS seperti yang dikatakan dalam dokumentasi, atau Anda akan membingungkan mereka yang datang setelah Anda. Jika Anda akan melakukan sesuatu yang berbeda, buat saja pengecualian Anda sendiri, seperti yang Anda katakan.
Robert C.Barth
1
Saya tidak setuju. Kecuali Anda memiliki skenario untuk menangkap pengecualian khusus Anda, tidak mungkin dalam kasus kesalahan konfigurasi, lebih baik untuk menggunakan kembali Jenis yang ada (ConfigurationErrorsException). Dan jika Anda membuat Type kustom, saya akan memperolehnya dari Type terkait seperti ConfigurationErrorsException.
Joe
@Robert & Joe- Saya tidak menyarankan bahwa pengecualian Kerangka yang ada harus digunakan secara tidak konsisten dengan fungsi yang dimaksudkan, hanya saja ada beberapa fleksibilitas selama kasus tertentu (nilai yang hilang) sesuai dengan kasus umum (ConfigurationErrorsException).
Dave Swersky
1
Mungkin ada masalah dengan ini jika Anda melempar pengecualian dalam aplikasi ASP.NET karena ConfigurationErrorsException dan kelas yang diturunkan darinya tidak terperangkap dalam metode OnError yang dilindungi atau oleh peristiwa Global ASAX Error. Lihat pertanyaan yang saya posting ini .... stackoverflow.com/questions/25299325/…
Mick
48

Secara pribadi, saya akan menggunakan InvalidOperationException , karena ini masalah dengan status objek - bukan sistem konfigurasinya. Lagi pula, bukankah seharusnya Anda mengizinkan setelan ini disetel oleh kode dan bukan konfigurasi juga? Bagian penting di sini bukanlah bahwa tidak ada baris di app.config, tetapi informasi yang diperlukan tidak ada.

Bagi saya, ConfigurationException (dan penggantinya, ConfigurationErrorsException - terlepas dari dokumen MSDN yang menyesatkan) adalah untuk kesalahan dalam menyimpan, membaca, dll. Dari Konfigurasi.

Tandai Brackett
sumber
Saya telah memilih InvalidOperationException, karena ditangani oleh metode OnError yang dilindungi Halaman ASP.NET, sementara ConfigurationErrorsException dan semua pengecualian yang diturunkan darinya tidak
Mick
2
Ini benar-benar akan mengejutkan saya, jika saya mendapatkan InvalidOperationException jika konfigurasi saya salah.
keuleJ
18

Seperti yang dikatakan Daniel Richardson, ConfigurationErrorsException adalah yang akan digunakan. Secara umum, hanya disarankan untuk membuat jenis Pengecualian kustom Anda sendiri jika Anda memiliki skenario untuk menanganinya. Dalam kasus kesalahan konfigurasi, yang biasanya berakibat fatal, hal ini jarang terjadi sehingga biasanya lebih tepat untuk menggunakan kembali jenis ConfigurationErrorsException yang ada.

Sebelum .NET 2.0, rekomendasinya adalah menggunakan System.Configuration.ConfigurationException . ConfigurationException menjadi usang di .NET 2.0, karena alasan yang tidak pernah jelas bagi saya, dan rekomendasi diubah untuk menggunakan ConfigurationErrorsException.

Saya menggunakan metode helper untuk membuang pengecualian sehingga mudah untuk mengubah pengecualian yang dilemparkan di satu tempat saat bermigrasi dari .NET 1.x ke 2.0, atau jika Microsoft memutuskan untuk mengubah rekomendasinya lagi:

if(string.IsNullOrEmpty(Configuration.AppSettings("foobar")))
{
   throw CreateMissingSettingException("foobar");
}

...

private static Exception CreateMissingSettingException(string name)
{
    return new ConfigurationErrorsException(
        String.Format
        (
        CultureInfo.CurrentCulture,
        Properties.Resources.MissingConfigSetting,
        name
        )
        );
}
Joe
sumber
16

Tentang apa System.Configuration.SettingsPropertyNotFoundException?

Laurent
sumber
IMO inilah jawaban sebenarnya. +1
LC
Tidak juga, karena: Memberikan pengecualian untuk objek SettingsProperty yang tidak ditemukan. Yang berasal dari: Digunakan secara internal sebagai kelas yang mewakili metadata tentang properti konfigurasi individu. Yang tidak sama dengan nilai konfigurasi yang hilang.
Karol Haliński
7

ConfigurationErrorsExceptionadalah pengecualian yang tepat untuk diterapkan dalam situasi yang Anda gambarkan. Versi sebelumnya dari dokumentasi MSDN untuk ConfigurationErrorsExceptionlebih masuk akal.

http://msdn.microsoft.com/en-us/library/system.configuration.configurationerrorsexception(VS.80).aspx

Rangkuman dan komentar MSDN sebelumnya adalah:

  • Pengecualian yang muncul ketika kesalahan sistem konfigurasi telah terjadi.
  • The ConfigurationErrorsException eksepsi dilemparkan ketika kesalahan terjadi ketika informasi konfigurasi yang sedang dibaca atau ditulis.
Daniel Richardson
sumber
7
dari dokumentasi: "API ini mendukung infrastruktur produk dan tidak dimaksudkan untuk digunakan secara langsung dari kode Anda. Menginisialisasi instance baru kelas ConfigurationErrorsException."
Oleg Sh
6

Kelas ConfigurationElement (yang merupakan kelas dasar dari banyak kelas terkait konfigurasi, seperti ConfigurationSection) memiliki metode yang disebut OnRequiredPropertyNotFound (ada juga metode pembantu lain). Anda mungkin bisa memanggilnya.

OnRequiredPropertyNotFound diimplementasikan seperti ini:

protected virtual object OnRequiredPropertyNotFound(string name) {
    throw new ConfigurationErrorsException(SR.GetString("Config_base_required_attribute_missing", new object[] { name }), this.PropertyFileName(name), this.PropertyLineNumber(name)); }
Gaspar Nagy
sumber
1

Saya akan menyedotnya dan menggulungnya sendiri ... tetapi sebelum Anda melakukannya, Mungkinkah sistem mengasumsikan nilai default untuk pengaturan konfigurasi ini? Saya biasanya mencoba melakukan itu untuk setiap pengaturan yang mungkin terlewatkan oleh orang-orang Manajemen Operasi ... (atau mungkin saya harus mengatakan, untuk sebanyak mungkin pengaturan - untuk beberapa pengaturan jelas tidak tepat untuk membuat sistem membuat keputusan default. ..)

secara umum pengecualian khusus tidak membutuhkan banyak usaha ... berikut ini contohnya ...

[Serializable]
public class MyCustomApplicationException : ApplicationException
{
    #region privates
    #endregion privates

    #region properties
    #endregion properties

    public MyCustomApplicationException (string sMessage,
        Exception innerException)
        : base(sMessage, innerException) { }
    public MyCustomApplicationException (string sMessage)
        : base(sMessage) { }
    public MyCustomApplicationException () { }

    #region Serializeable Code
    public MyCustomApplicationException (
       SerializationInfo info, StreamingContext context)
        : base(info, context) { }
    #endregion Serializeable Code
}
Charles Bretana
sumber
2
MSDN: ... aplikasi yang perlu membuat pengecualiannya sendiri, [...] mendapatkan pengecualian kustom dari kelas Exception. Awalnya dianggap bahwa pengecualian khusus harus berasal dari kelas ApplicationException; namun dalam prakteknya hal ini tidak terbukti menambah nilai yang signifikan.
Gaspar Nagy
Ya, saya pikir itu karena programmer MS yang mengkodekan kerangka kerja memperoleh banyak pengecualian CLR dari ApplicationException, sehingga menghancurkan pentingnya perbedaan tersebut .. Saya masih melakukannya, karena saya tidak melihat ada salahnya ...
Charles Bretana
1

Metode alternatif yang dapat Anda gunakan untuk file konfigurasi Anda adalah dengan menggunakan bagian konfigurasi khusus sebagai lawan AppSettings. Dengan cara itu Anda dapat menentukan bahwa properti IsRequireddan sistem konfigurasi akan menangani pemeriksaan ini untuk Anda. Jika properti hilang itu akan melempar ConfigurationErrorsExceptionjadi saya kira itu mendukung jawaban bahwa Anda harus menggunakan pengecualian itu dalam kasus Anda.

Yogh
sumber
0

Aturan umum saya adalah:

  1. Jika kasus konfigurasi yang hilang tidak terlalu umum dan saya yakin saya tidak ingin menangani kasus ini secara berbeda dari pengecualian lainnya, saya hanya menggunakan kelas "Pengecualian" dasar dengan pesan yang sesuai:

    lempar Pengecualian baru ("pesan saya di sini")

  2. Jika saya ingin, atau berpikir ada kemungkinan besar saya ingin menangani kasus ini dengan cara yang berbeda dari kebanyakan pengecualian lainnya, saya akan menggulung tipe saya sendiri seperti yang telah disarankan orang di sini.

Hershi
sumber
0

Saya cenderung tidak setuju dengan premis pertanyaan Anda:

Singkatnya, saya memerlukan pengecualian standar yang harus dibuang ketika pengaturan konfigurasi aplikasi hilang atau berisi nilai yang tidak valid. Anda akan berpikir Kerangka memiliki pengecualian seperti itu yang dimasukkan ke dalamnya untuk digunakan aplikasi. (Tampaknya memang demikian, tetapi ditandai usang, dan digantikan oleh sesuatu yang jauh lebih besar cakupannya.)

Menurut dokumentasi MSDN di System.Exception ( Exception Class , Anda seharusnya tidak memberikan pengecualian untuk kesalahan input pengguna, karena alasan kinerja (yang telah ditunjukkan oleh orang lain di Stack Overflow dan di tempat lain). Ini tampaknya masuk akal karena baik - mengapa fungsi Anda tidak bisa mengembalikan false jika input pengguna salah dimasukkan, dan kemudian membuat aplikasi keluar dengan anggun? Ini tampaknya lebih merupakan masalah desain daripada masalah yang harus dilemparkan Exception.

Seperti yang ditunjukkan orang lain, jika Anda benar - benar harus membuat pengecualian - karena alasan apa pun - tidak ada alasan mengapa Anda tidak dapat menentukan jenis Pengecualian Anda dengan mewarisi dari System.Exception.

Matt Jordan
sumber
2
Mengapa kinerja penting dalam skenario khusus ini? IUC, maka pengecualian dilemparkan tepat sekali dan prosesnya kemungkinan akan turun setelahnya (tentu saja, setelah menampilkan munculan yang bagus kepada pengguna). (dilanjutkan ...)
2
Mengembalikan kode kesalahan alih-alih memberikan pengecualian bisa menyakitkan, karena Anda kemudian harus menyebarkan informasi kesalahan sendiri ke tumpukan panggilan. Anda harus menggunakan pengecualian untuk kesalahan yang relatif jarang terjadi yang mungkin disebarkan melalui beberapa bingkai tumpukan. Keduanya berlaku di sini.
1
Anda melewatkan sesuatu: "ketika setelan konfigurasi aplikasi hilang atau berisi nilai yang tidak valid", itu tidak sama dengan masukan pengguna yang buruk. Ini adalah konfigurasi dasar yang hilang. Harus menjadi pengecualian khusus dan harus menghentikan aplikasi agar tidak berjalan.
jcollum
2
Dalam aplikasi khusus ini, hampir seluruhnya didorong oleh pengaturan di file konfigurasi. Jika pengaturan tidak ada di dalamnya (di mana mereka dienkripsi), aplikasi tidak dapat melanjutkan, dan harus dihentikan. Pengecualian diperlukan secara virtual.
Mike Hofer
1
Ini pasti bisa masuk ke semantik, dan struktur kode Anda jelas akan menentukan implementasi terbaik untuk situasi Anda. Namun, jika Anda memiliki kebebasan memerintah dalam desain, saya masih akan pergi dengan objek untuk mencatat kesalahan dan keluar dengan anggun atas pengecualian, kinerja menjadi masalah atau tidak.
Matt Jordan
-2

Anda dapat mencoba mewarisi XML Exception, atau hanya menggunakannya.

StingyJack
sumber