Click here to Skip to main content
15,896,153 members
Articles / Web Development / ASP.NET

ASP.NET AJAX Controls and Extenders

Rate me:
Please Sign up or sign in to vote.
4.80/5 (36 votes)
13 Sep 2012LGPL351 min read 314.8K   4.5K   200  
This tutorial examines the new Visual Studio 2008 Server Control and Server Control Extender. A compendium of tips, tricks, and gotchas, it is a comprehensive tutorial that will provide readers with the skills necessary to start building advanced AJAX-enabled custom controls with Visual Studio.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace SessionTimeoutTool
{
    [System.Drawing.ToolboxBitmap(typeof(TimeoutWatcherAjaxControl), "dilbert.ico")]
    [ToolboxData("<{0}:TimeoutWatcherAjaxControl runat=server></{0}:TimeoutWatcherAjaxControl>")]
    public class TimeoutWatcherAjaxControl: ScriptControl
    {

        #region private members

        private mode _timeoutMode = mode.CustomHandler;
        private int _interval = 1000;
        private readonly int MINUTES = 60000;
        private readonly int SECONDS = 1000;

        public event EventHandler Timeout;

        private string _redirectPage;
        private string _message;
        private string _popupCSSClass = string.Empty;

        protected System.Web.UI.Timer _sessionTimer = null;
        private UpdatePanel _timeoutPanel = null;

        private ScriptMode _scriptMode = ScriptMode.ServerSide;

        #endregion

        #region enums

        public enum mode
        {
            PageRedirect,
            PopupMessage,
            ExtendTime,
            CustomHandler
        }

        public enum ScriptMode
        {
            ServerSide,
            ClientSide
        }

        #endregion

        #region public properties

        public mode TimeoutMode
        {
            get { return _timeoutMode; }
            set { _timeoutMode = value; }
        }
        public string RedirectPage
        {
            get { return _redirectPage; }
            set { _redirectPage = value; }
        }

        public string TimeoutMessage
        {
            get { return _message; }
            set { _message = value; }
        }

        public string PopupCSSClass
        {
            get { return _popupCSSClass; }
            set { _popupCSSClass = value; }
        }

        public ScriptMode RunMode
        {
            get { return _scriptMode; }
            set { _scriptMode = value; }
        }

        #endregion

        #region onload

        protected override void OnLoad(EventArgs e)
        {
            //retrieve session timeout period from server
            System.Web.SessionState.HttpSessionState state 
                = HttpContext.Current.Session;
            
            //convert minutes to milliseconds
            _interval = state.Timeout * MINUTES;

            if (RunMode == ScriptMode.ServerSide)
            {
                //create new ajax components
                UpdatePanel timeoutPanel = GetTimeoutPanel();
                System.Web.UI.Timer sessionTimer = GetSessionTimer();
                if (TimeoutMode == mode.ExtendTime)
                    sessionTimer.Interval = _interval - (45 * SECONDS);
                else
                    sessionTimer.Interval = _interval;

                //add timer to update panel
                timeoutPanel.ContentTemplateContainer.Controls.Add(
                    sessionTimer);

                //add update panel to timeout watcher control
                this.Controls.Add(timeoutPanel);
            }
        }

        private System.Web.UI.Timer GetSessionTimer()
        {
            if (null == _sessionTimer)
            {
                _sessionTimer = new System.Web.UI.Timer();
                _sessionTimer.Tick += new EventHandler<EventArgs>(SessionTimer_Tick);
                _sessionTimer.Enabled = this.TimerEnabled;
                _sessionTimer.ID = this.ID + "SessionTimeoutTimer";
            }
            return _sessionTimer;
        }

        private UpdatePanel GetTimeoutPanel()
        {
            if (null == _timeoutPanel)
            {
                _timeoutPanel = new UpdatePanel();
                _timeoutPanel.ID = this.ID + "SessionTimeoutPanel";
                _timeoutPanel.UpdateMode = UpdatePanelUpdateMode.Always;
            }
            return _timeoutPanel;
        }


        #endregion

        #region on timeout


        protected void SessionTimer_Tick(object sender, EventArgs e)
        {
            switch (TimeoutMode)
            {
                case mode.ExtendTime:
                    //do nothing, page has reposted
                    //45 seconds before timeout
                    break;
                case mode.PageRedirect:
                    Redirect(RedirectPage);
                    break;
                case mode.PopupMessage:
                    DisableTimer();
                    BuildPopup();
                    break;
                case mode.CustomHandler:
                default:
                    DisableTimer();
                    OnTimeout();
                    break;
            }
        }

        private void OnTimeout()
        {
            if (Timeout != null)
                Timeout(this, EventArgs.Empty);
        }

        public bool TimerEnabled
        {
            get
            {
                object timedOut = ViewState[this.ID + "TimedOutFlag"];
                if (null == timedOut)
                    return true;
                else
                    return Convert.ToBoolean(timedOut);
            }
            set 
            {
                GetSessionTimer().Enabled = value;
                ViewState[this.ID + "TimedOutFlag"] = value;
            }
        }

        private void DisableTimer()
        {
            this.TimerEnabled = false;
        }

        private void AddMessageToPopupPanel(Panel popup, string message)
        {
            Literal lit = new Literal();
            if (string.IsNullOrEmpty(message))
            {
                lit.Text = "<center>Your session timed out at " + DateTime.Now.ToLongTimeString() + " after " + (_interval / MINUTES).ToString() + " minutes of inactivity.</center>";
            }
            else
                lit.Text = "<center>" + TimeoutMessage + "</center>";
            popup.Controls.Add(lit);
        }

        private void AddCSSStylesToPopupPanel(Panel popup)
        {
            if (string.IsNullOrEmpty(PopupCSSClass))
            {
                popup.Style.Add("position", "absolute");
                popup.Style.Add("top", "100px");
                popup.Style.Add("left", "200px");
                popup.Style.Add("background-color", "#F5F7F8");
                popup.Style.Add("border-style", "groove");
                popup.Style.Add("padding", "15px");
                popup.Style.Add("z-index", "999");
            }
            else
            {
                popup.CssClass = PopupCSSClass;
            }
        }

        private static void AddOKButtonToPopupPanel(Panel popup, EventHandler handlePopupButton)
        {
            Literal litCenterOpen = new Literal();
            litCenterOpen.Text = "<br/><center>";
            Button but = new Button();
            but.Text = "OK";
            but.Click += handlePopupButton;
            Literal litCenterClose = new Literal();
            litCenterClose.Text = "</center>";
            popup.Controls.Add(litCenterOpen);
            popup.Controls.Add(but);
            popup.Controls.Add(litCenterClose);
        }

        void but_Click(object sender, EventArgs e)
        {
            this.TimerEnabled = true;
        }

        private void BuildPopup()
        {
            UpdatePanel p = GetTimeoutPanel();
            Panel popup = new Panel();

            AddCSSStylesToPopupPanel(popup);

            popup.Height = 50;
            popup.Width = 125;
            popup.Style.Add("position", "absolute");
            popup.Style.Add("z-index", "999");

            AddMessageToPopupPanel(popup, TimeoutMessage);
            EventHandler handlePopupButton = new EventHandler(but_Click);
            AddOKButtonToPopupPanel(popup, handlePopupButton);
            p.ContentTemplateContainer.Controls.Add(popup);
        }

        private void Redirect(string redirectPage)
        {
            if (!string.IsNullOrEmpty(redirectPage))
            {
                    Context.Response.Redirect(
                        VirtualPathUtility.ToAbsolute(
                        redirectPage));
            }
        }


        #endregion

        private string _customHandlerJScript;

        public string CustomHandlerJScript
        {
            get { return _customHandlerJScript; }
            set { _customHandlerJScript = value; }
        }
        public TimeoutWatcherAjaxControl()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        #region Implement ScriptControl

        protected override IEnumerable<ScriptDescriptor>
        GetScriptDescriptors()
        {
            if (RunMode == ScriptMode.ClientSide)
            {
                ScriptControlDescriptor descriptor = new ScriptControlDescriptor("SessionTimeoutTool.TimeoutWatcherBehavior", this.ClientID);
                descriptor.AddProperty("interval", _interval);
                descriptor.AddProperty("timeoutMode", _timeoutMode);
                descriptor.AddProperty("message", _message);
                descriptor.AddProperty("redirectPage" , string.IsNullOrEmpty(_redirectPage) ? "" : VirtualPathUtility.ToAbsolute(_redirectPage));
                descriptor.AddProperty("customHandlerJScript", _customHandlerJScript);
                yield return descriptor;
            }
        }

        // Generate the script reference
        protected override IEnumerable<ScriptReference>
                GetScriptReferences()
        {
            if (RunMode == ScriptMode.ClientSide)
            {
                yield return new ScriptReference("SessionTimeoutTool.TimeoutWatcherBehavior.js", this.GetType().Assembly.FullName);
                yield return new ScriptReference("SessionTimeoutTool.Timer.js", this.GetType().Assembly.FullName);
            }
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Software Developer (Senior)
United States United States
James is a program writer for a respectable software company. He is also a Microsoft MVP.

Comments and Discussions