Menggunakan ConfigurationManager untuk memuat konfigurasi dari lokasi arbitrer

124

Saya sedang mengembangkan komponen akses data yang akan digunakan di situs web yang berisi campuran halaman ASP dan ASP.NET klasik, dan memerlukan cara yang baik untuk mengelola pengaturan konfigurasinya.

Saya ingin menggunakan kustom ConfigurationSection, dan untuk halaman ASP.NET ini berfungsi dengan baik. Tetapi ketika komponen dipanggil melalui interop COM dari halaman ASP klasik, komponen tersebut tidak berjalan dalam konteks permintaan ASP.NET dan karena itu tidak memiliki pengetahuan tentang web.config.

Apakah ada cara untuk memberi tahu ConfigurationManageruntuk hanya memuat konfigurasi dari jalur arbitrer (misalnya ..\web.configjika rakitan saya ada di /binfolder)? Jika ada maka saya berpikir komponen saya dapat kembali ke itu jika default ConfigurationManager.GetSectionkembali nulluntuk bagian kustom saya.

Pendekatan lain untuk ini akan diterima!

Mike Powell
sumber

Jawaban:

124

Coba ini:

System.Configuration.ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath); //Path to your config file
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
Ishmaeel
sumber
Bagaimana saya bisa mendapatkan nilai strConfigPath secara terprogram untuk aplikasi ASP.NET WebForms saya yang dihosting di sub.domain.com/virtualDir2 dan jalur C: \ Portals \ App1 \ v2 dan file konfigurasi di C: \ Portals \ App1 \ v2 \ web.config ?
Kiquenet
1
@Kiquenet: Inti dari pertanyaannya adalah bahwa strConfigP adalah lokasi yang berubah - ubah . Dengan kata lain, Anda memutuskan apa jalurnya, alih-alih mengandalkan kerangka kerja untuk mencoba memuat file konfigurasi dari lokasi konvensionalnya. Saya akan berasumsi Server.MapPath akan memberi Anda lokasi absolut untuk file apa pun dalam solusi Anda.
Ishmaeel
1
Mungkinvar config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~/web.config");
Kiquenet
@Kikuen Pasti.
Ucho
66

Solusi lain adalah menimpa jalur file konfigurasi lingkungan default.

Saya menemukan solusi terbaik untuk pemuatan file konfigurasi jalur non-sepele, khususnya cara terbaik untuk melampirkan file konfigurasi ke dll.

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", <Full_Path_To_The_Configuration_File>);

Contoh:

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", @"C:\Shared\app.config");

Rincian lebih lanjut dapat ditemukan di blog ini .

Selain itu, jawaban lain ini memiliki solusi yang sangat baik, lengkap dengan kode untuk menyegarkan konfigurasi aplikasi dan IDisposableobjek untuk mengatur ulang kembali ke keadaan semula. Dengan solusi ini, Anda dapat membuat konfigurasi aplikasi sementara tetap tercakup:

using(AppConfig.Change(tempFileName))
{
    // tempFileName is used for the app config during this context
}
Saturn Technologies
sumber
1
Ini juga berfungsi untuk memuat file web.config. Saya menggunakannya untuk memuat web.config alih-alih app.config untuk aplikasi konsol terkait tugas. ;)
James Wilkins
1
Ini (dan jawaban lainnya di sini) tidak berhasil untuk saya. Saya telah menambahkan kode di program.cs - function: Main (). Konfigurasi saya berisi pengalihan versi rakitan (lihat stackoverflow.com/questions/30165393/… ) tetapi pengalihan tidak memengaruhi saat konfigurasi diubah secara manual.
Vortex852456
1
Apakah Anda menggunakan "APP_CONFIG_FILE"?
Saturn Technologies
40

Jawaban Ishmaeel umumnya berfungsi, namun saya menemukan satu masalah, yaitu penggunaan OpenMappedMachineConfigurationtampaknya kehilangan grup bagian yang Anda warisi dari machine.config. Ini berarti Anda dapat mengakses bagian kustom Anda sendiri (yang semuanya diinginkan OP), tetapi bukan bagian sistem normal. Misalnya, kode ini tidak akan berfungsi:

ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath);
Configuration configuration = ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
MailSettingsSectionGroup thisMail = configuration.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;  // returns null

Pada dasarnya, jika Anda meletakkan jam tangan di configuration.SectionGroups, Anda akan melihat bahwa system.net tidak terdaftar sebagai SectionGroup, jadi tidak bisa diakses melalui saluran normal.

Ada dua cara yang saya temukan untuk mengatasi ini. Yang pertama, yang tidak saya suka, adalah mengimplementasikan ulang grup bagian sistem dengan menyalinnya dari machine.config ke web.config Anda sendiri misalnya

<sectionGroup name="system.net" type="System.Net.Configuration.NetSectionGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
  <sectionGroup name="mailSettings" type="System.Net.Configuration.MailSettingsSectionGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <section name="smtp" type="System.Net.Configuration.SmtpSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </sectionGroup>
</sectionGroup>

Saya tidak yakin aplikasi web itu sendiri akan berjalan dengan benar setelah itu, tetapi Anda dapat mengakses sectionGroups dengan benar.

Solusi kedua adalah membuka web.config Anda sebagai konfigurasi EXE, yang mungkin lebih dekat dengan fungsi yang dimaksudkan:

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = strConfigPath };
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
MailSettingsSectionGroup thisMail = configuration.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;  // returns valid object!

Saya berani mengatakan tidak ada jawaban yang diberikan di sini, baik milik saya atau Ishmaeel, yang cukup menggunakan fungsi ini seperti yang dimaksudkan oleh desainer NET. Tapi, ini sepertinya berhasil untuk saya.

Gavin
sumber
1
Anda juga dapat menggunakan overload ConfigurationManager.OpenExeConfiguration (String) untuk tujuan yang sama. Lihat: codeproject.com/KB/dotnet/mysteriesofconfiguration3.aspx#t2_1
Ohad Schneider
10

Selain jawaban Ismail, metode tersebut OpenMappedMachineConfiguration()akan selalu mengembalikan Configurationobjek. Jadi untuk memeriksa untuk melihat apakah itu dimuat Anda harus memeriksa HasFileproperti di mana benar berarti itu berasal dari sebuah file.

Joseph Daigle
sumber
9

Jawaban yang diterima salah !!

Ini melontarkan pengecualian berikut saat mengakses properti AppSettings:

Tidak dapat mentransmisikan objek jenis 'System.Configuration.DefaultSection' untuk mengetik 'System.Configuration.AppSettingsSection'.

Inilah solusi yang tepat:

System.Configuration.ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "YourFilePath";
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
Yakub
sumber
1
ya, ini pasti jawaban yang benar! Terima kasih telah memposting jawaban Anda.
Fabio Milheiro
Saya pikir System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration bahkan lebih benar tetapi tidak tersedia untuk .NET Core jadi dalam hal ini jawaban ini tampaknya menyelesaikan pekerjaan.
Risord
4

Saya memberikan nilai konfigurasi ke Word hosted .nET Compoent sebagai berikut.

Komponen Perpustakaan Kelas .NET dipanggil / dihosting di MS Word. Untuk memberikan nilai konfigurasi ke komponen saya, saya membuat winword.exe.config di folder C: \ Program Files \ Microsoft Office \ OFFICE11. Anda harus dapat membaca nilai konfigurasi seperti yang Anda lakukan di .NET Tradisional.

string sMsg = System.Configuration.ConfigurationManager.AppSettings["WSURL"];
Iftikhar Ali
sumber
1

Untuk ASP.NET gunakan WebConfigurationManager:

var config = WebConfigurationManager.OpenWebConfiguration("~/Sites/" + requestDomain + "/");
(..)
config.AppSettings.Settings["xxxx"].Value;
Javier Cañon
sumber
0

Gunakan pemrosesan XML:

var appPath = AppDomain.CurrentDomain.BaseDirectory;
var configPath = Path.Combine(appPath, baseFileName);;
var root = XElement.Load(configPath);

// can call root.Elements(...)
JoelFan
sumber