ASP.net: Custom Web.config Sections and Elements

On occasion you will find it necessary to add your own configuration sections to your web application’s web.config configuration file. This allows you to encapsulate configuration options needed by your components into a manageable section within your applications configuration. The information you place in the custom configuration section should be items that may change frequently.

By adding configuration information used by your components to the web,config file you can at any time without recompiling your application code alter the behavior and functionality of your components by changing these configuration options. This is because the web.config file is monitored by the ASP.net worker process and when ever it is altered the application is restarted and the configuration is re-read so that all components utilizing the configuration will receive the updates.

Here is what the config section definition looks like. This is added to the ‘configSections’ portion of the web.config files (at the top usually). This section defines what other sections are within the rest of the configuration file and which can be read by the web application. It takes a name which is the name of th e


<section name="myconfigsection" type="MyAssembly.MyConfigSection, MyAssembly, Version=1.0.0.0, Culture=neutral" requirePermission="false"/>

Here is what the config section we will be working from looks like


<myconfigsection>
    <mylistoffoods>
        <add name="bacon" enjoy="true" />
<
add name="steak" enjoy="true" />
<add name="celery" enjoy="false" /> </mylistoffoods>

</myconfigsection>
The first thing to do is create what I call a ‘Configuration Helper’ class which is responsible for pulling our configuration section and exposing it to our component as a public property which our code can access. Here is the class:


using System;
using System.Configuration;
namespace MyAssembly
{
    /// 
    /// This class is used to retrieve most important settings from web.config
    /// 
    public class ConfigurationHelper
    {

#region Private Fields private static MyConfigSection _myConfigSection =

            (MyConfigSection)ConfigurationManager.GetSection("myconfigsection");
        #endregion
        #region Public Properties
        /// 
        /// Gets the client admin logging section.
        /// 
        /// The client admin logging section.
        public static MyConfigSection MyConfigSection
        {
            get{ return _MyConfigSection; }
        }
        #endregion
    }
}

Next you create the class which represents the actual configuration section you introduced to the web.config. It is through this class that you will be able to access your Foods collection.


using System.Configuration;
namespace MyAssembly
{
    /// 
    /// Represents the section within
    /// the web.config.
    /// 
    public class MyConfigSection : ConfigurationSection
    {
        #region Public Properties
        /// 
        /// Returns a collection of event handler configurations
        /// 
        /// The event handlers.
        [ConfigurationProperty("mylistoffoods")]
        public FoodCollection MyListOfFoods
        {
            get
            {
                return this["mylistoffoods"] as FoodCollection;
            }
        }
        #endregion
    }
}

Next we need to create a class which will represent a food in the collection. Here is the class:


using System.Configuration;
namespace MyAssembly
{
    /// 
    /// Represents the configuration for an event handler 
    /// within the web.config
    /// 
    public class Food : ConfigurationElement
    {
        #region Public Properties
        /// 
        /// Gets the name of the event handler.
        /// 
        /// The name.
        [ConfigurationProperty("name", IsRequired = true)]
        public string Name
        {
            get
            {
                return this["name"] as string;
            }
        }
        /// 
        /// Gets a value indicating whether  I like the food
        /// 
        /// true if like; otherwise, false.
        [ConfigurationProperty("enjoy", IsRequired = true)]
        public bool Enjoy
        {
            get
            {
                return (bool) this["enabled"];
            }
        }
        #endregion
    }
}

Next we create a class to represent a collection of foods. Here is the class:


using System.Configuration;
namespace MyAssembly
{
    /// 
    /// Represents a collection of event handlers pulled
    /// from the web.config
    /// 
    public class FoodCollection : ConfigurationElementCollection
    {
        #region Overrides of ConfigurationElementCollection
        /// 
        /// When overridden in a derived class, creates a new .
        /// 
        /// 
        /// A new .
        /// 
        protected override ConfigurationElement CreateNewElement()
        {
            return new EventHandler();
        }
        /// 
        /// Gets the element key for a specified configuration element when overridden in a derived class.
        /// 
        /// 
        /// An  that acts as the key for the specified .
        /// 
        /// The  to return the key for. 
        ///                 
        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((EventHandler) element).Name;
        }
        #endregion
    }
}

Well that’s all there is to it now within your components code you simply call your Configuration Helper and pull the food collection and use the foods as you need to.

ASP.net: Sending Application Mail through Google Apps (GMail)

I ran into a little gotcha when setting up a new web application to send email through the Google Apps SMTP servers. When you read the Google support documentation on setting up a client to send email through their SMTP server you will see there are 2 options SSL, TSL with a different port for each.
When writing the C# code to send the email there is an option to on the .Net SmtpClient object called ‘EnableSsl’. You of course need to set this to true but the gotcha comes in when you setup the SMTP server and port in your web.config file. You would assume since the option ‘EnableSsl’ refers to ‘SSL’ you would need to use port 465 for SSL as outlined by Google in their documentation. But. you would be wrong to assume that and on every call to send an email within your application you will run into a ‘Time Out’.
I don’t know everything about .Net mail but apparently ‘EnableSsl’ doesn’t really mean SSL it means TSL. I say this because as soon as I changed the SMTP server’s port in my web.config from the SSL port of 465 to the TSL port of 587 as outlined by Google my mail sent without issue.
Hopefully this will save someone a lot of time.
Web.config Setup:

  <system.net>
    <mailSettings>
      <smtp from="noreply@yourdomain.com">
        <network host="smtp.gmail.com" password="******" userName="noreply@yourdomain.com" port="587" />
      </smtp>
    </mailSettings>
  </system.net>

C# Send Mail Code:

            try
            {
                MailMessage message = new MailMessage();

                message.From = new MailAddress(tbxEmail.Text);
                message.To.Add(new MailAddress(_supportEmail));

                message.Subject = tbxSubject.Text;
                message.IsBodyHtml = false;
                message.Priority = MailPriority.High;
                message.Body = tbxMessage.Text;


                SmtpClient client = new SmtpClient();
                client.EnableSsl = true;
                client.Send(message);

                return true;
            }
            catch (Exception ex)
            {
                ExceptionHandler handler = new ExceptionHandler();
                handler.LogException(ex,
                    SeverityLevel.Critical,
                    "Contact Form Message could not be sent to support email",
                    GetType(),
                    "SendMessageEmail");
            }

JavaScript: Confirm User Action Script

Code:

<script language="javascript" type="text/javascript">
    function ConfirmDeleteSomething() {
        return confirm("Warning: This Something will be permanently deleted. Would you still like to continue? ");
    }



<asp:LinkButton ID="lbtnDelete" runat="server" 
    OnClick="lbtnDelete_Click"
    CausesValidation="false"
    OnClientClick="return ConfirmDeleteSomething()">Delete Something

Summary:

To make sure that a user is actually sure they want to perform an unrecoverable action, such as deleting something, you may want to add a confirmation dialog warning the user of what their potential actions may do.

To do this using JavaScript simply add a function which calls the ‘confirm’ command and call that function through the ‘OnClientClick’ event of your button control in ASP.net.

DNN: Cannot hit Page_Load event of Control

If you are developing a DotNetNuke module and are in the middle of coding and testing that module within a DNN installation and have noticed that you cannot get Visual Studio to enter the Page_Load event of your User Controls and its driving you insane!

Here is the simple solution, make sure your module definition has the Cache Time set to 0. I have found that this is most likely the reason you never see the Page_Load or any other initialization methods hit when debugging your module.

0

ASP.net: TabContainer Maintain Selected Tab Index with Hidden Field

JavaScript which hooks to the OnClientActiveTabChanged=”OnTabChanged” event of the TabContainer. When the event is called the currently selected tab index is pulled and saved to the hidden form field.

<script type="text/javascript">
function OnTabChanged(sender, args) {
var tabControl = $get("").control;
var currentIndex = tabControl.get_activeTabIndex();
$get("").value = currentIndex;
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Hidden form filed added to ASCX or ASPX view.

<asp:HiddenField ID="hfSelectedIndex" runat="server" />

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Method for setting the ActiveTabIndex of the TabContainer if there is a value in the hidden form field.

        private void SetCurrentTab()
        {
            if(!string.IsNullOrEmpty(hfSelectedIndex.Value))
            {
                int value;
                if (int.TryParse(hfSelectedIndex.Value, out value))
                    tcStoreEditor.ActiveTabIndex = value;
            }
        }

Call the SetCurrentTab method in the Page_Load event to set the selected index if one exists.

        protected void Page_Load(object sender, EventArgs e)
        { 
            if (!Page.IsPostBack)
            {
                //Some Method Calls Here
            }
 
            SetCurrentTab();
        }