26
ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

Embed Size (px)

Citation preview

Page 1: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

ASP.net Form State

Jeremy Boyd,Senior Technical Lead - IntergenMSDN Regional Director – New Zealand

Page 2: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

Todays ObjectivesDiscuss ViewState– Used for supplemental state transmission

Event Identification– Hidden fields used to distinguish events– ViewState used to trigger change notification

events

Per-client state– ViewState– Session– Cookies

Page 3: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

Todays ObjectivesAlternative inter-page state propagation– Query string– Items collection

Page 4: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

ViewStateTo complete the control-based model, additional state must be transferred with each post back– Many HTML elements do not have their values sent in

a POST• table, span, div, p, li, etc.

– If the value of one of these elements is changed in a server-side control, it should retain that value across multiple requests

– Additional hidden input element is generated with each Page rendering called __VIEWSTATE

– Contains a base64-encoded string with supplemental state

Page 5: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

<%@ Page Language="C#" %><html><script runat="server">protected void Page_Load(object src, EventArgs e){ if (IsPostBack) { int op1 = int.Parse(_op.Value); int op2 = int.Parse(_sum.InnerText); _sum.InnerText = (op1+op2).ToString(); }}</script><body> <form runat="server"> <h2>ASP.NET accumulator page</h2> <input size="2" type="text" id="_op" runat="server"/> Sum:<span id="_sum" runat="server">0</span> <p><input type="submit" value="Add" /></p> </form></body></html>

<%@ Page Language="C#" %>

Sample Page relying on ViewState

Page 6: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

<html>

<body> <form name="_ctl0" method="post" action="accumulator.aspx" id="_ctl0"> <input type="hidden" name="__VIEWSTATE" value="dDwtMTE3NzEwNDc2Njs7PvcRil1nMNe70yha9afq+YEvj46N" />

<h2>ASP.NET accumulator page</h2> <input name="_op" id="_op" type="text" size="2" /> Sum:<span id="_sum"></span> <p> <input type=submit value="Add" /> </p> </form></body></html>

Sample Page – HTML output

Page 7: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

Decoding ViewStateViewState is persisted as a tuple-based data structure and encoded as a base64 string

t<1181972940;t<;l<i<1>;>;l<t<;l<i<5>;>;l<t<p<p<l<Text;>;l<1;>>;>;;>;>>;>>;>r(M * 6kN

dDwxMTgxOTcyOTQwO3Q8O2w8aTwxPjs+O2w8dDw7bDxpPDU+Oz47bDx0PHA8cDxsPFRleHQ7PjtsPDE7Pj47Pjs7Pjs+Pjs+Pjs+coPvKE0gKu8gNg298/1rC07unJE=

Page 8: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

ViewStateDecoderAvailable at – http://www.develop.com/devresources/

Page 9: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

Disabling ViewStateViewState can be disabled for individual controls, an entire page, or even an entire application

<%@ Page Language="C#" EnableViewState="False" %><html><!-- ... -->

<%@ Page Language="C#" %><html><body> <form runat="server" ID="Form1"> <input type="text" id="_op" runat="server" EnableViewState="false" /> <span id="_span1" runat="server" EnableViewState="false" /> <p><input type="button" value="Enter" runat="server" /></p> </form></body></html>

<%@ Page Language="C#" %>

<%@ Page Language="C#" EnableViewState="False" %>

Page 10: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

Protecting ViewStateASP.NET provides two mechanisms for protecting ViewState– Tamper-proofing using a hashcode (SHA1 or MD5)– Encryption using Triple DES symmetric algorithm

(3DES)

Tamper-proofing can be enabled at the Page level (on by default)– <%@ Page enableViewStateMac='true' %>

Or at the application or machine level– <!-- in web.config or machine.config -->– <pages enableViewStateMac='true' />

Page 11: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

ViewState EncryptionMust be enabled at the machine level:– <machineKey validation='3DES' />

Significantly increases the size of ViewState - use with caution!No need to encrypt if already using SSLFor deployment on a WebFarm, you must specify the same validation key on all machines:– <machineKey validation='3DES'

validationKey='7DFB068D0FC3D9E2E3C2BCA32DF9509DEFF71B8F44DF95578CCFCD2B6EA50475BEE615AF0E64072EC07A1D4720F11A5125947C592512BA72290812F911963CC8' />

Page 12: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

using System;using System.Text;using System.Security;using System.Security.Cryptography;

class App { static void Main(string[] argv) { int len = 48; if (argv.Length > 0) len = int.Parse(argv[0]);

byte[] buff = new byte[len/2]; RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetBytes(buff); StringBuilder sb = new StringBuilder(len); for (int i=0; i<buff.Length; i++) sb.Append(string.Format("{0:X2}", buff[i]));

Console.WriteLine(sb); }}

Generating a Validation Key

Page 13: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

Identifying server-side events

Server-side events are issued during a POST request– Not obvious which controls fired events with a

generic POST• Was a select box changed?• Was button 1 pressed?• Was button 2 pressed?

– ASP.NET propagates additional event information• Hidden field __EVENTTARGET stores the control id that

issued the event• Hidden field __EVENTARGUMENT stores any parameters to

the event

Page 14: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

<%@ Page Language="C#" %><html><script runat="server">protected void OnLinkButton(object src, EventArgs e){ _message.Text = "You clicked the link button!"; }

protected void OnIndexChanged(object src, EventArgs e) { _message.Text = string.Format("You changed the index to {0}!", _ddl.SelectedItem.Value);}</script><body><form runat="server"> <h2>ASP.NET event page</h2> <asp:LinkButton runat="server" Text="Click Me!" OnClick="OnLinkButton" /> <br/> <asp:DropDownList runat="server" ID="_ddl" AutoPostBack="true" OnSelectedIndexChanged="OnIndexChanged"> <asp:ListItem Selected="True" Value="1"> item 1 </asp:ListItem> <asp:ListItem Value="2"> item 2 </asp:ListItem> <asp:ListItem Value="3"> item 3 </asp:ListItem> <asp:ListItem Value="4"> item 4 </asp:ListItem> </asp:DropDownList> <br/> <asp:Label id="_message" runat="server" EnableViewState="false" /></form></body></html>

Page with Multiple Events

Page 15: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

<html><body> <form name="_ctl0" method="post" action="event.aspx" id="_ctl0"><input type="hidden" name="__EVENTTARGET" value="" /><input type="hidden" name="__EVENTARGUMENT" value="" /><input type="hidden" name="__VIEWSTATE" value="..." /><script language="javascript">function __doPostBack(eventTarget, eventArgument) { var theform; if (window.navigator.appName.toLowerCase().indexOf("netscape") > -1){ theform = document.forms["_ctl0"]; } else { theform = document._ctl0; } theform.__EVENTTARGET.value = eventTarget.split("$").join(":"); theform.__EVENTARGUMENT.value = eventArgument; theform.submit();}</script> <h2>ASP.NET event page</h2> <a href="javascript:__doPostBack('_ctl1','')">Click Me!</a> <br/> <select name="_ddl" onchange="__doPostBack('_ddl','')" language="javascript" id="_ddl"> ...

Event Page Rendering

Page 16: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

Change notification eventsServer-side controls that issue change notification events rely on ViewState– Prior value stored in ViewState– During subsequent POST current value is

compared with value cached in ViewState and change notification issued if different

Corollary: do not disable ViewState on controls whose server-side change events you are handling

Page 17: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

Explicit use of ViewStateViewState can also be used as a means to store client-specific state

public class PurchasePage : Page{ private void Page_Load(object sender, EventArgs e) { ArrayList cart = (ArrayList)ViewState["Cart"]; if (cart == null) { cart = new ArrayList(); ViewState["Cart"] = cart; } // Use items stored in ArrayList }

Page 18: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

Session StateSession state is used to store individual data for a user during page interaction– Session state is scoped by a single client session, and

is tagged with a unique (and hard to guess) session ID– The session ID is transmitted between the client and

server using cookies (or munged URLs if cookieless mode is enabled)

– Accessed through the Session property of a page, which references the current HttpSession object provided by the HTTP runtime

More on session and scalability later...

Page 19: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

// Inside a page of the applicationprotected void Submit_Click(Object sender, EventArgs e) { Session["Age"] = AgeField.Value; // save age user entered // ... }

// Inside another page of the application // only let user vote if he/she is over 18if (((int)Session["Age"]) >= 18) VoteButton.Enabled = true;else VoteButton.Enabled = false;

Session State – Sample usage

Page 20: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

CookiesClient-side cookies can be used to store user preferences/information– Server requests client to set cookie in response– Client sends cookie values in subsequent requests– Cookies may be persisted if the Expires property– Browsers limit cookie data -- only 4096 bytes guaranteed– Clients may disable cookies

Cookie interaction controlled with two collections:– Request.Cookies - cookies sent by client– Response.Cookies - cookies you are requesting client to

set

Page 21: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

protected void Page_Load(object sender, EventArgs e) { if (Request.Cookies["Age"] == null) Response.Cookies.Add(new HttpCookie("Age", "21")); else { // use existing cookie value... int age = int.Parse(Request.Cookies["Age"].Value); }}

Using Cookies in ASP.net

Page 22: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

QueryString StateState can be passed between pages by appending a query string to the URL– Must be passed as name/value pairs– Restricted to URL compatible strings

• Must use % to represent restricted characters as encoded (including /.#?;:$,+@&={}|\^[]')

– Indicate query string with '?' character– Delimit name/value pairs with '&' character– Access query string values through the

indexer in HttpRequest

http://turtle.net.nz/test.aspx?name=joe&age=21

?name=joe&age=21

Page 23: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

private void _signupButton_Click(object sender, System.EventArgs e){ StringBuilder url = new StringBuilder(); // prepare query string url.Append("ThankYou.aspx?firstname="); url.Append(_firstname.Text); url.Append("&lastname="); url.Append(_lastname.Text); url.Append("&zipcode="); url.Append(_zipcode.Text); Response.Redirect(url.ToString()); }

private void Page_Load(object sender, System.EventArgs e){ StringBuilder msg = new StringBuilder(); msg.Append("<b>Registered user:</b> "); msg.Append(Request["firstname"]); msg.Append(" "); msg.Append(Request["lastname"]); msg.Append("<br/> <b>location=</b>"); msg.Append(Request["zipcode"]); _summary.InnerHtml = msg.ToString();}

Signup.aspx.cs

ThankYou.aspx.cs

Request["firstname"]

Request["lastname"]

Request["zipcode"]

QueryString Example

Page 24: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

Context.Items StateThe Items collection of HttpContext can be used to store per-request state– Useful when passing data between elements

in the pipeline (like modules)– Can be used to pass data between pages

when using Server.Transfer

Page 25: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

private void _signupButton_Click(object sender, System.EventArgs e){ Context.Items["firstname"] = _firstname.Text; Context.Items["lastname"] = _lastname.Text; Context.Items["zipcode"] = _zipcode.Text; Server.Transfer("ThankYou.aspx"); }

private void Page_Load(object sender, System.EventArgs e){ StringBuilder msg = new StringBuilder(); msg.Append("<b>Registered user:</b> "); msg.Append(Context.Items["firstname"]); msg.Append(" "); msg.Append(Context.Items["lastname"]); msg.Append("<br/> <b>location=</b>"); msg.Append(Context.Items["zipcode"]); _summary.InnerHtml = msg.ToString();}

Signup.aspx.cs

ThankYou.aspx.cs

Context.Items["firstname"]Context.Items["lastname"]Context.Items["zipcode"]

Context.Items["firstname"]

Context.Items["lastname"]

Context.Items["zipcode"]

Context.Items State Example

Page 26: ASP.net Form State Jeremy Boyd, Senior Technical Lead - Intergen MSDN Regional Director – New Zealand

SummaryASP.NET developers must be aware of the various types of state forms use– ViewState is used for controls whose contents does not

propagate with traditional POST bodies– Change notifications managed via ViewState– Server-side events use supplemental hidden fields

Several types are available for use– ViewState - client-specific for POST requests to same page– Session state - client-specific tied to browser session– Cookie state - client specific string pairs– Query string state - for passing data between pages– Items collection - for transferring data between pages