Saturday, June 05, 2010

How does .Net Framework track Postback values : Asp.Net

When page life cycle executes, for all controls in a page, if a control implements IPostBackDataHandler interface .net framwork invokes, IPostBackDataHandler's LoadPostData(string postKey, NameValueCollection postCollection)

public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
    ///
    /// Process your data here
    ///
    return false;
}

postCollection:
Is a NameValueCollection which consist of all input filelds present in the page along with their values agaisnt corrosponding names.
  • ctrl00$txtFirstName - FirstName
  • ctrl00$txtSurname - Surname
  • ctrl00$txtAddress - Address
Remember .net framwork use a format of ctl00_txtName as the id of the dom element. (.net control.ClientID) and exactly the same but separater is $ for name, ctrl00$txtName. (.net control UniqueID)
postKey
Is the name of the corresponding control. So easyly we can retrive the value of the input field like String postedValue = postCollection[postDataKey];
In terms of writting HTML, when you write a html, you cant just use Response.Write("<input..... ) but you can write a simple web-control (in your case checkbox) and add instance of your custom check box to the page. Unless the control get added to the page, page life cycle wont be able to do anyting with your control. For build a simple web-control you can just extend WebControl class in System.Web.UI and to handle postbacks you may implement IPostBackDataHandler interface as well.
Example:

CustomCheckBox cchkBox = new CustomCheckBox();
this.Page.Controls.Add(cchkBox);

This is a complete example of Custom Checkbox which has a hidden field to hold it's value.

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public class CustomCheckBox : WebControl,
                                IPostBackDataHandler,
                                INamingContainer
{
    public bool Checked
    {
        get
        {
            return (bool)(ViewState["Checked"] ?? (ViewState["Checked"] = false));
        }
 
        set
        {
            ViewState["Checked"] = value;
        }
    }
    public bool AutoPostBack { getset; }
    public event EventHandler CheckChanged;
    public string Label { getset; }
    public virtual bool LoadPostData(string postDataKey,
                                    NameValueCollection postCollection)
    {
        bool presentValue = this.Checked;
        String postedValue = postCollection[postDataKey];
        if (!presentValue.Equals(postedValue))
        {
            this.Checked = postedValue.Equals("on") ? true : false;
            return true;
        }
        return false;
    }
    public virtual void RaisePostDataChangedEvent()
    {
        OnCheckChanged(EventArgs.Empty);
    }
    protected virtual void OnCheckChanged(EventArgs e)
    {
        if (CheckChanged != null)
            CheckChanged(this, e);
    }
    protected override void Render(HtmlTextWriter output)
    {
        output.Write(string.Format("<input type='checkbox' {0}{1} />",
            this.Checked ? " checked='checked'" : string.Empty,
            this.AutoPostBack ? string.Format(
                " onclick=\"javascript:__doPostBack('{0}','');\"",
                this.UniqueID) :
            string.Empty));
        output.Write(string.Format("<span>{0}</span>"this.Label));
        output.Write(string.Format("<input type='hidden' value='{0}' id='{1}' name='{2}' />",
            this.Checked ? "off" : "on"this.ClientID, this.UniqueID));
    }
}

Friday, June 04, 2010

How to post values to diffent page using HttpWebRequest : Asp.net

Using Asp.net HttpWebRequest object we can post data to external page and get a HttpWebResponse

string strId = "regid789654";
string strName = "Charith";
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = "userid=" + strId;
postData += ("&username=" + strName);
byte[] data = encoding.GetBytes(postData);
HttpWebRequest request =
    (HttpWebRequest)WebRequest.Create("http://www.domain.com/cart.asp");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
Stream newStream = request.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Close();
 
StreamReader sr = new StreamReader(request.GetResponse().GetResponseStream());
string result = sr.ReadToEnd();
sr.Close();

Thursday, June 03, 2010

How to find which page a IFRAME embeded in - Asp.net

There are some common senarios where we need to find which page we are in and which domain the parent page belongs to. Specially when we work with banners and advertiesments this may be useful. However, this post demonstrates how to find domain and file name using round trip to client. But for the first request this parameters will not be available but from the second request onwards those parameters will be available to the code behind.

<%@ Page Language="C#"  %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
    <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript" language="javascript"></script>
    <script type="text/javascript" language="javascript">
        $(document).ready(function () {
            var url = parent.location.href.replace('http://''');
            if (url.search('.aspx?') != -1) url = url.split("?")[0];
            var location = window.location.href;
            if (location.search('page') == -1 && location.search('domain') == -1) {
                var parts = url.split("/");
                var d = parts[0];
                if (parts.length > 1) {
                    var fileName = parts[parts.length - 1];
                    var p = fileName.split(".")[0];
                    window.location.href = location + "?page=" + p + "&domain=" + d;
                }
                else
                    window.location.href = location + "?domain=" + d;
            }
        });
    </script>
    <script runat="server">
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            string source = this.Page.Request.QueryString.Get("page");
            string domain = this.Page.Request.QueryString.Get("domain");
            if (!string.IsNullOrEmpty(domain))
            {
                ///
                /// Use domain
                ///
            }
            if (!string.IsNullOrEmpty(source))
            {
                if (source.StartsWith("A"))
                {
                    ///
                    /// A Group page
                    /// 
                }
                else if (source.StartsWith("B"))
                {
                    ///
                    /// B Group page
                    ///
                }
            }
        }       
    </script>
</head>
<body>
    <form id="form1" runat="server">
        Test 
    </form>
</body>
</html>
 

Hyperlink rewritting with anchor tags - Asp.net

Idea is to rewrite all hyperlinks to have a anchor tag appended when you focus the page in to a anchor tag in a aspx page.In this senario, I have occupied a static anchor tag, but easyliy we can utilize this dynamically from query string

<%@ Page Language="C#"  %>
<html>
<head id="Head1" runat="server">
    <title></title>
    <script language="javascript" type="text/javascript">
    </script>
    <script runat="server">
        protected override void Render(HtmlTextWriter writer)
        {
            string a = "C123456";
            StringBuilder sb = new StringBuilder();
            HtmlTextWriter htw = new HtmlTextWriter(new System.IO.StringWriter(sb));
            base.Render(htw);
            string html = sb.ToString();
            int lc = html.IndexOf("<a", 0);
            while (lc > 0)
            {
                int lb = html.IndexOf("href=", lc) + 6;
                int ub = html.IndexOf("\"", lb);
                string link = html.Substring(lb, ub - lb);
                if (!link.Contains("#"))
                {
                    string newLink = string.Format("{0}#{1}", link, a);
                    html = html.Replace(link, newLink);
                }
                if (lc + 2 < html.Length)
                    lc = html.IndexOf("<a", lc + 2);
                else lc = -1;
            }
            writer.Write(html);
        }
        protected void ShowSection(object sender, EventArgs e)
        {
            this.Response.Redirect("Test2.aspx#c2345"true);
        }        
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Button runat="server" ID="btnPostback" 
            OnClick="ShowSection" Text="Show Section" />
        <asp:HyperLink runat="server" ID="HyperLink1" 
            NavigateUrl="~/Test1.aspx" Text="Normal Link" />        
        <asp:HyperLink runat="server" ID="HyperLink2" 
            NavigateUrl="~/Test2.aspx" Text="Normal Link" />
        <asp:HyperLink runat="server" ID="HyperLink3" 
            NavigateUrl="~/Test3.aspx" Text="Normal Link" />
        <asp:HyperLink runat="server" ID="HyperLink4" 
            NavigateUrl="~/Test4.aspx" Text="Normal Link" />
        <asp:HyperLink runat="server" ID="HyperLink5" 
            NavigateUrl="~/Test5.aspx" Text="Normal Link" />
    </form>
</body>
</html>

Monday, May 31, 2010

ASP.net and ATL Server debugging - IIS 7

Cause:
Error while trying to run project: Unable to start debugging on the web server. The server does not support debugging of ASP.NET or ATL Server applications. Run setup to install the Visual Studio .NET server components. If setup has been run, verify that a valid URL has been specified.


You may also want to refer to the ASP.NET and ATL Server debugging topic in the online documentation. Would you like to disable future attempts to debug ASP.NET pages for this project?
Posible reson is to have in-compatile web.config after converting asp.net 3.5 application to asp.net 4.0 application.

Example: having modules and httpModules in the same web.config

<configuration>
  ...
  <system.web>
    ...
    <httpModules>
      <add name="SEOModule"
         type="WebSphere.Ngate.SEOModule.SEOModule, WebSphere.Ngate.SEOModule" />
    </httpModules>
  </system.web>
  <system.webServer>
    <modules>
      <add name="SEOModule" preCondition="managedHandler"
         type="WebSphere.Ngate.SEOModule.SEOModule, WebSphere.Ngate.SEOModule" />
    </modules>
    ...
  </system.webServer>
</configuration>

Removing httpModules section will resolve the problem

<configuration>
  ...
  <system.web>
    ...
  </system.web>
  <system.webServer>
    <modules>
      <add name="SEOModule" preCondition="managedHandler"
         type="WebSphere.Ngate.SEOModule.SEOModule, WebSphere.Ngate.SEOModule" />
    </modules>
    ...
  </system.webServer>
</configuration>

Wednesday, May 26, 2010

Asp.net Dom Validation script : for custom validators

//<script>
var Page_DomValidationVer = "2";
var Page_IsValid = true;
var Page_BlockSubmit = false;
 
function ValidatorUpdateDisplay(val) {
    if (typeof (val.display) == "string") {
        if (val.display == "None") {
            return;
        }
        if (val.display == "Dynamic") {
            val.style.display = val.isvalid ? "none" : "inline";
            return;
        }
    }
    val.style.visibility = val.isvalid ? "hidden" : "visible";
}
 
function ValidatorUpdateIsValid() {
    var i;
    for (i = 0; i < Page_Validators.length; i++) {
        if (!Page_Validators[i].isvalid) {
            Page_IsValid = false;
            return;
        }
    }
    Page_IsValid = true;
}
 
function ValidatorHookupControl(control, val) {
    if (typeof (control.Validators) == "undefined") {
        control.Validators = new Array;
        var ev = control.onchange;
        var func = new Function("ValidatorOnChange('" + control.id + "');");
        control.onchange = func;
    }
    control.Validators[control.Validators.length] = val;
}
 
function ValidatorGetValue(id) {
    var control;
    control = document.getElementById(id);
    if (typeof (control.value) == "string") {
        return control.value;
    }
    if (typeof (control.tagName) == "undefined" && typeof (control.length) == "number") {
        var j;
        for (j = 0; j < control.length; j++) {
            var inner = control[j];
            if (typeof (inner.value) == "string" && (inner.type != "radio" || inner.status == true)) {
                return inner.value;
            }
        }
    }
    return "";
}
 
function Page_ClientValidate() {
    var i;
    for (i = 0; i < Page_Validators.length; i++) {
        ValidatorValidate(Page_Validators[i]);
    }
    ValidatorUpdateIsValid();
    Page_BlockSubmit = !Page_IsValid;
    return Page_IsValid;
}
 
function ValidatorCommonOnSubmit() {
    var returnValue = !Page_BlockSubmit;
    Page_BlockSubmit = false;
    return returnValue;
}
 
function ValidatorOnChange(controlID) {
    var cont = document.getElementById(controlID);
    var vals = cont.Validators;
    var i;
    for (i = 0; i < vals.length; i++) {
        ValidatorValidate(vals[i]);
    }
    ValidatorUpdateIsValid();
}
 
function ValidatorValidate(val) {
    val.isvalid = true;
    if (typeof (val.evalfunc) == "function") {
        val.isvalid = val.evalfunc(val);
    }
    ValidatorUpdateDisplay(val);
}
 
function ValidatorOnLoad() {
    if (typeof (Page_Validators) == "undefined")
        return;
 
    var i, val;
    for (i = 0; i < Page_Validators.length; i++) {
        val = Page_Validators[i];
        var evalFunction = val.getAttribute("evaluationfunction");
        if (typeof (evalFunction) == "string") {
            eval("val.evalfunc = " + evalFunction + ";");
        }
        var isValidAttribute = val.getAttribute("isvalid");
        if (typeof (isValidAttribute) == "string") {
            if (isValidAttribute == "False") {
                val.isvalid = false;
                Page_IsValid = false;
            }
            else {
                val.isvalid = true;
            }
        } else {
            val.isvalid = true;
        }
        var controlToValidate = val.getAttribute("controltovalidate");
        if (typeof (controlToValidate) == "string") {
            ValidatorHookupControl(document.getElementById(controlToValidate), val);
        }
    }
    Page_ValidationActive = true;
}
 
function RegularExpressionValidatorEvaluateIsValid(val) {
    var value = ValidatorGetValue(val.getAttribute("controltovalidate"));
    if (value == "")
        return true;
    var rx = new RegExp(val.getAttribute("validationexpression"));
    var matches = rx.exec(value);
    return (matches != null && value == matches[0]);
}
 
function ValidatorTrim(s) {
    var m = s.match(/^\s*(.*\S)\s*$/);
    return (m == null) ? "" : m[1];
}
 
function RequiredFieldValidatorEvaluateIsValid(val) {
    return (ValidatorTrim(ValidatorGetValue(val.getAttribute("controltovalidate"))) 
        != ValidatorTrim(val.getAttribute("initialvalue")));
}

Saturday, May 22, 2010

Resetable Panel Asp.Net - Reset all values to default values of child controls and nested panels.

Well, there is no reset method for asp.net panel by the time of this article. But certainly we can implement a reset method by extending functionalities of required controls.
PS: If this functionality is widely use I would implement something like this. But it is only for less then 10 controls don't walk on this root.
As asp.net is extensible, we can extend Label, Textbox to have DefaultValues property and a mechanism to on and off (LoadDefaultValue which is true by default) the feature so that we can use it like ordinary controls.
  1. Implement's key feature is an interface called IXControl 
  2. Which has three members. Namely string DefaultValues { get; set; }, bool LoadDefault { get; set; } and void Reset();
  3. All X Controls implement this interface. 
  4. Inside the Reset method of each control, call common helper method called ResetProperties passing parameters, this control and DefaultValues property.
  5. DefaultValues propety should be a list of comma seperated { PropertyName=ProperyValue } pairs. Example DefaultValues="Text=DefaultText;ForeColor=Red;BackColor=Blue;Visible=false ... N
  6. Inside ResetProperties we decode DefaultValues string using string split and populate PropertyValue list
  7. Then use Reflection to go through each property of control and if propety name matchs one of in the list, set the value of the property using PropertyInfo
  8. Inside the panel Reset method, we call ResetInteranl so it will hock up all the child controls. Call Reset method using IXControl interface determining if the child type is IXControl.
  9. There is a catch, we need to go to children only if control is not a XPanel. Because once we call the Reset of XPanel it know how to reset all of it's children by itself
Extended controls and IXPanel interface : PS I have hosted custom controls in a separate assembly called Active.Web.UI.Controls. So you might nedd to change to namespace and assembly to get this working accroding to your control location.

Code:
/// <summary>
/// ControlManager and PropertyValue classes
/// </summary>
 
public class ControlManager
{
    public static void ResetProperties(Control control, string defaultValues)
    {
        if (string.IsNullOrEmpty(defaultValues)) return;
        List<PropertyValue> pvs = new List<PropertyValue>();
        foreach (string pv in defaultValues.Split(";".ToCharArray()))
        {
            string[] s = pv.Split("=".ToCharArray());
            if (s.Length == 2 && !string.IsNullOrEmpty(s[0]))
                pvs.Add(new PropertyValue() { Property = s[0].Trim(), Value = s[1] });
        }
        foreach (PropertyInfo p in control.GetType().GetProperties())
        {
            PropertyValue pv = pvs.Find(x => x.Property.Equals(p.Name));
            if (pv != null)
            {
                if (p.PropertyType.Equals(typeof(string)))
                    p.SetValue(control, pv.Value, null);
                else if (p.PropertyType.Equals(typeof(Color)))
                {
                    try { p.SetValue(control, new ColorConverter().ConvertFromString(pv.Value), null); }
                    catch { }
                }
                else if (p.PropertyType.Equals(typeof(bool)))
                {
                    bool value;
                    if (bool.TryParse(pv.Value, out value))
                        p.SetValue(control, value, null);
                }
                ///
                /// You can extend this for any other criteria
                ///
            }
        }
    }
}
public class PropertyValue
{
    public string Property { getset; }
    public string Value { getset; }
}
 
/// <summary>
/// IXControl interface
/// </summary>
 
public interface IXControl
{
    string DefaultValues { getset; }
    bool LoadDefault { getset; }
    void Reset();
}
 
/// <summary>
/// XLabel 
/// </summary>
 
public class XLabel : LabelIXControl
{
    public string DefaultValues { getset; }
    public bool LoadDefault { getset; }
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        if (this.LoadDefault && !this.Page.IsPostBack) this.Reset();
    }
    public void Reset()
    {
        ControlManager.ResetProperties(thisthis.DefaultValues);
    }
}
 
/// <summary>
/// XTextbox
/// </summary>
 
public class XTextBox : TextBoxIXControl
{
    public string DefaultValues { getset; }
    public bool LoadDefault { getset; }
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        if (this.LoadDefault && !this.Page.IsPostBack) this.Reset();
    }
    public void Reset()
    {
        ControlManager.ResetProperties(thisthis.DefaultValues);
    }
}
 
/// <summary>
/// XPanel
/// </summary>
 
public class XPanel : PanelIXControl
{
    public string DefaultValues { getset; }
    public bool LoadDefault { getset; }
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        if (this.LoadDefault && !this.Page.IsPostBack) this.Reset();
    }
    public void Reset()
    {
        ControlManager.ResetProperties(thisthis.DefaultValues);
        this.ResetInternal(this.Controls);
    }
    private void ResetInternal(ControlCollection controlCollection)
    {
        foreach(Control control in controlCollection)
        {
            if (control is IXControl) ((IXControl)control).Reset();
            if (control.Controls.Count > 0 && !control.GetType().Equals(typeof(XPanel)))
                this.ResetInternal(control.Controls);
        }
    }
}

Markup:

<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ Register Assembly="Active.Web.UI.Controls" Namespace="Active.Web.UI.Controls" TagPrefix="active" %>
<%@ Import Namespace="System.Drawing" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head2" runat="server">
    <title>Reset Panel</title>
    <script runat="server">
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            for (int i = 0; i < 30; i++)
            {
                this.xpnlContainer.Controls.Add(
                    new XLabel() { DefaultValues = String.Format("Text={0};Visible=true;ForeColor=Red""Label " + i) });
                this.xpnlContainer.Controls.Add(
                    new XTextBox() { DefaultValues = String.Format("Text={0};Visible=true;BackColor=Blue""Textbox " + i) });
                XPanel panel =new XPanel() { BackColor = System.Drawing.Color.Red, Visible = false, DefaultValues = "Visible=true" };
                panel.Controls.Add(new XLabel() { Text = "Nested Label - Init", DefaultValues = "Text=Nested Label Default" });
                this.xpnlContainer.Controls.Add(panel);
            }
        }
        public void Reset(object sender, EventArgs e)
        {
            this.xpnlContainer.Reset();
        }        
    </script>
</head>
<body>
    <form id="form2" runat="server">
    <div>
        <active:XPanel runat="server" ID="xpnlContainer" />
        <asp:Button runat="server" ID="btnReset" Text="Reset" OnClick="Reset" />
        <asp:Button runat="server" ID="btnPostback" Text="Postback" />
    </div>
    </form>
</body>
</html>

Monday, May 17, 2010

How to build login session timeout prompt message using jQuery

ASP.Net forms authentication session renew its authentication ticket only when the total escape time exceeds the half of the configured timeout. Say for example if you have 20 minutes configured in the web.config.
  1. Login time : 2.00 pm – Authentication ticket created (Expire on 2.20 pm)
  2. Do a postback: 2.05 pm. Before 10 minutes, which is a half of the configured timeout – Authentication ticket will not get renewed (Expire on 2. 20 pm)
  3. Leave browser – no postbacks
  4. Do a postback: 2.12 pm. After 10 minutes, which is a half of the configured timeout – Authentication ticket will get renewed (Expire on 2.32 pm)
If you need to have a time out message in your web page, we have to use a java script function with a counter. When counter comes to a certain point, say 2 minutes before the actual forms time out show the timeout message. However according to above explanation there is no constant timeout value for the first half of the timeout. Therefore we have to calculate the timeout and pass it to the java script function on each postback.

Example:





Test page inherit from the page base:

public class PageBase : Page
{
    private string startUpStript = @"
        var timeout = ({0} * 60) - 10;
        var timeEscaped = 0;
        var timerTicks = 0;
        var showBefore = 30
        function CountDown() {{
            if (timeEscaped < timeout - showBefore) {{
                setTimeout(CountDown, 1000);
                timeEscaped++;
            }}
            else
                ShowTimer();
        }}
        function ShowTimer() {{
            $("".LoginTimeout"").fadeIn();
            DisplayTime();
        }}
        function DisplayTime() {{
            if (timerTicks < showBefore) {{
                $("".LoginTimeout .TimeoutMessage .Timeout"").text(showBefore - timerTicks);
                timerTicks++;
                setTimeout(DisplayTime, 1000);
            }}
            else ShowTimedOutMsg();
        }}
        function ShowTimedOutMsg() {{
            $("".LoginTimeout .TimeoutMessage"").fadeOut();
            $("".LoginTimeout .LoggedOutMessage"").fadeIn();
        }}
        $(document).ready(function () {{
            CountDown()
        }});
    ";
    public LoginTimeout LoginTimeout
    {
        get { return (LoginTimeout)Session["LoginTimeout"]; }
        set { Session["LoginTimeout"] = value; }
    }
    public override void ProcessRequest(HttpContext context)
    {
        base.ProcessRequest(context);
        if (context.User != null && context.User.Identity.IsAuthenticated)
        {
            FormsIdentity identity = this.User.Identity as FormsIdentity;
            FormsAuthenticationTicket ticket = identity.Ticket;
            if (this.LoginTimeout == null || this.LoginTimeout.IssuedTime != ticket.IssueDate)
            {
                this.LoginTimeout = new LoginTimeout()
                {
                    IssuedTime = ticket.IssueDate,
                    TimeOut = FormsAuthentication.Timeout
                };
            }
            else
            {
                TimeSpan adjustment = DateTime.Now - this.LoginTimeout.IssuedTime;
                this.LoginTimeout.TimeOut = FormsAuthentication.Timeout - adjustment;
            }
        }
    }
    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        if (this.LoginTimeout != null)
            this.Page.ClientScript.RegisterClientScriptBlock(
                this.GetType(),
                this.GetType().Name,
                string.Format(this.startUpStript, this.LoginTimeout.TimeOut.Minutes),
                true);
    }
 
}
public class LoginTimeout
{
    public DateTime IssuedTime { getset; }
    public TimeSpan TimeOut { getset; }
}

Test page markup:

<%@ Page Language="C#" AutoEventWireup="true"
     CodeBehind="Test.aspx.cs" Inherits="ActiveTest.Test" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Test Page</title>
    <style type="text/css">
        body { font-family:Tahomafont-size:11px; }
        p { padding:0margin:0; }
        .LoginTimeoutdisplay:none; 
                       padding:10px; 
                       background-color:#ffbd8c; 
                       height:15px; 
                       border:dotted 1px #f57313; 
                       text-align:center; 
                       width:300px; }
        .LoginTimeout .LoggedOutMessage,
        .LoginTimeout .TimeoutMessage { position:absolute; }
        .LoginTimeout .LoggedOutMessage { display:none; }
    </style>
    <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript" language="javascript"></script>
</head>
<body>
    Test Page
    <form method="get" action="Page2.html">
        <div class="LoginTimeout">
            <div class="TimeoutMessage">
                <p>Your login session will timeout in <strong>
                <span class="Timeout"></span></strong> seconds</p></div>
            <div class="LoggedOutMessage">
                <p>Your login sesson has timed out. You need to <a href="Login.aspx">
                login again</a></p></div>
        </div>
    </form>
</body>
</html>

Test page code behind:

namespace ActiveTest
{
    public partial class Test : PageBase
    {
 
    }
} 

Reference: Understanding the Forms Authentication Ticket and Cookie

Azure Storage Account Types

Defferent Types of Blobs Block blobs store text and binary data. Block blobs are made up of blocks of data that can be managed individually...