2009-06-08 1 views
2

Я хотел бы сохранить набор пар ключ/значение в настройках приложения моего веб-приложения ASP.NET, но я не нахожу простой способ сделать это. Например, эти twoquestions говорят мне, что StringDictionary и т. Д. Не будут сериализованы в XML и предполагают, что мне придется катить мою собственную реализацию. Но, похоже, это должно быть проще сделать; в конце концов, web.config - это XML и < applicationSettings> по существу представляет собой набор пар ключ/значение, поэтому мне кажется, что я пропускаю что-то очевидное. Учитывая мой конкретный случай ниже, действительно ли мне нужно сворачивать свою сериализацию, или есть более простой способ обхода?Есть ли способ использовать словарь-подобную коллекцию в качестве объекта «Параметры приложения»?

Входящее веб-приложение является базовой формой контакта, которая отправляет электронное письмо различным получателям на основе значения параметра; например http://www.examplesite.com/Contact.aspx?recipient=support отправит письмо по адресу [email protected]

Цель состоит в том, чтобы иметь возможность добавлять или удалять получателей (или изменять их адреса), редактируя файл web.config, чтобы мне не пришлось перекомпилировать и легко поддерживать различные конфигурации в тестовых и производственных средах. Например:

// I can use something like this for the sender address 
SmtpMsg.From = New MailAddress(My.Settings.EmailSender) 

// And then just edit this part of web.config to use 
// different addresses in different environments. 
<setting name="EmailSender" serializeAs="String"> 
<value>[email protected]</value> 
</setting> 

// I want something like this for the recipients 
SmtpMsg.To.Add(My.Settings.Recipients("support")) 

// and presumably some sort of equivalent xml in web.config 
// maybe something like this??? 
<recipients> 
    <item name="support" serializeAs="String"> 
    <value>[email protected]</value> 
    </item> 
    <!-- add or remove item elements here --> 
</recipients> 

редактирования: заменить VB комментарии W/C# комментарии из-код-раскраска

ответ

5

simplist образом, очевидно, будет просто бросить их в настройках приложения, но это не было бы очень аккуратно:

<appSettings> 
    <add key="EmailSupport" value="[email protected]" /> 
    <add key="EmailSales" value="[email protected]" /> 
</appSettings> 

Тогда в вашем коде вы просто делаете что-то вроде:

if (!string.IsNullOrEmpty(Request["recipient"])) { 
    string recipientEmail = 
     WebConfigurationManager.AppSettings["Email" + Request["recipient"]]; 
    // Send your email to recipientEmail 
} 

Если вы хотите быть немного аккуратнее, вы можете создать собственный Configuration Section, как это (C# я боюсь, но the docs have VB а):

namespace EmailSystem { 
    public class EmailRecipientsSection : ConfigurationSection { 
    [ConfigurationProperty("emailSender", IsRequired = true, IsKey = false)] 
    public string EmailSender { 
     get { return (string)this["name"]; } 
     set { this["name"] = value; } 
    } 

    [ConfigurationProperty("emailRecipients", IsDefaultCollection = true)] 
    public EmailRecipientCollection EmailRecipients { 
     get { 
     var emailRecipientCollection = 
       (EmailRecipientCollection) base["emailRecipients"]; 
     return emailRecipientCollection; 
     } 
    } 
    } 

    public class EmailRecipientCollection : ConfigurationElementCollection { 
    public EmailRecipientElement this[int index] { 
     get { return (EmailRecipientElement) BaseGet(index); } 
     set { 
     if (BaseGet(index) != null) { 
      BaseRemoveAt(index); 
     } 
     BaseAdd(index, value); 
     } 
    } 

    public new EmailRecipientElement this[string name] { 
     get { return (EmailRecipientElement) BaseGet(name); } 
    } 

    protected override ConfigurationElement CreateNewElement() { 
     return new EmailRecipientElement(); 
    } 

    protected override object GetElementKey(ConfigurationElement element) { 
     return ((EmailRecipientElement) element).Name; 
    } 
    } 

    public class EmailRecipientElement : ConfigurationElement { 
    [ConfigurationProperty("name", IsRequired = true, IsKey = true)] 
    public string Name { 
     get { return (string) this["name"]; } 
     set { this["name"] = value; } 
    } 

    [ConfigurationProperty("emailAddress", IsRequired = true)] 
    public string EmailAddress { 
     get { return (string) this["emailAddress"]; } 
     set { this["emailAddress"] = value; } 
    } 
    } 
} 

Затем в вашей сети.конфиг есть что-то вроде этого:

<configSections> 
    [...] 
    <section name="EmailSystem" type="EmailSystem, AssmeblyName" /> 
</configSections> 

<EmailSystem emailSender="[email protected]"> 
    <emailRecipients> 
    <clear /> 
    <add name="Support" emailAddress="[email protected]" /> 
    <add name="Sales" emailAddress="[email protected]" /> 
    </emailRecipients> 
</EmailSystem> 

Тогда вы можете позвонить в это:

emailRecipient = Request["recipient"]; 

var emailSystem = ConfigurationManager.GetSection("EmailSystem") 
        as EmailRecipientsSection; 

string recipientEmail = emailSystem.EmailRecipients[emailRecipient].emailAddress; 

// send email to recipientEmail. 
+1

Это почти идеальный ответ. У этого есть быстрое и простое решение, которое достаточно хорошо (то есть просто используйте ), а также более тщательное решение, которое обращается к корню моего вопроса (т. Е. Коллекции в web.config). Также отличный образец кода. Если бы я мог проголосовать за это снова, я бы это сделал. Спасибо. – Matt

+0

Нет проблем - комментарий достаточно благодарен :) - Думаю, если бы я портировал образцы на VB, это было бы прекрасно;) –

3

Вы можете сделать несколько вещей, хотя, честно говоря, я думаю, что это самый простой:

<appSettings> 
    <add key="testValues" value="[email protected], [email protected], [email protected]" /> 
</appSettings> 

Тогда вы можете получить объект через:

String[] temp = 
ConfigurationManager.AppSettings.GetValues("testValues").ToString().Split(','); 

, а затем сделать простое заявление Еогеаспа к извлечения. Вы могли бы даже установить это как статический объект для кэширования, чтобы быстрее получить. :)

Надеется, что это помогает,

JP

EDIT: альтернативный сценарий предполагает:

<appSettings file="test.config"> 
<!-- other settings to default to if test.config doesn't exist --> 
</appSettings> 

В этом случае, если у вас есть test.config файл существует в тестовой среде , вызов AppSettings.GetValues ​​() будет выполнен против этого файла. Если файл test.config не существует, класс ConfigurationManager будет использовать значения в узле appSettings в файле web.config.

+0

Может быть, я недоразумение, но похоже, что это дало бы мне несколько значений для одного ключа; Я ищу несколько ключей, каждый с одним значением. – Matt

+0

Затем, если вы хотите использовать несколько ключей с одним значением, просто используйте несколько строк с ключевыми словами и назовите их соответствующим образом. Из вашего объяснения казалось, что вам нужно несколько значений за ключ. Общая идея заключается в том, что вы можете использовать файл test.config в тестовой среде и значения по умолчанию (поскольку test.config не будет существовать в процессе производства) будет работать, если test.config не существует. – Jonathan

+0

ОК, теперь я получаю информацию о ключах (должен был подумать, что до того, как я прокомментировал); и атрибут файла кажется удобным для замены тестовых значений. – Matt

Смежные вопросы