1.49k likes | 1.67k Views
State management and Caching in ASP.NET. Gill Cleeren Microsoft Regional Director MVP ASP.NET Ordina Belgium. State management and Caching in ASP.NET. Gill Cleeren Microsoft Regional Director MVP ASP.NET Ordina Belgium. About Gill. .net architect Ordina (ordina.be)
E N D
State management and Caching in ASP.NET Gill CleerenMicrosoft Regional DirectorMVP ASP.NETOrdina Belgium
State management and Caching in ASP.NET Gill CleerenMicrosoft Regional DirectorMVP ASP.NETOrdina Belgium
About Gill • .net architect Ordina (ordina.be) • Microsoft Regional Director (theregion.com) • MVP ASP.net • Writing: • .net magazine • Blogs • MSDN • Speaking: • TechDays • Usergroups(Visug, Biwug, Besug) • Ineta speaker • Blog: www.snowball.be • Email: gill.cleeren@ordina.be • Twitter: gillcleeren • MSN: gillcleeren@hotmail.com
Agenda • State Management • Caching in ASP.NET
State management agenda • ViewState • QueryString • CrossPage posting • Cookies • Session state • Application state
State management • HTTP is stateless • After a request, client is disconnected from server • Good for scalability • 1000s of users and still enough memory! • Drawback: you need to storing techniques for between requests! • ASP.NET State Management is solution • Choose based on • what you need to store • How long... • Mostly, you’ll combine several options
Available options • ViewState • Query String • Cookies • Session state • Application state • Caching
View State • Best for storing information within the bounds of a single page • Natively used by ASP.NET controls • allows them to retain their properties between postbacks • Add own data through the view state collection called ViewState • This is a dictionary ViewState["Counter"] = 1;
View State • Retrieving the value • NullReferenceException when searching a non-existent key int counter; if (ViewState["Counter"] != null) { counter = (int)ViewState["Counter"]; }
DEMO ViewState
Storing Objects in View State • You can store any object in ViewState • ASP.NET must be able to convert it into a stream of bytes • Serialization of the object is needed • If not serializable, error is thrown [Serializable] public class Customer { public string FirstName; public string LastName; public Customer(string firstName, string lastName) { FirstName = firstName; LastName = lastName; } }
Storing Objects in View State • If a class (MSDN) is not Serializable, it cannot be stored • Other options like in-process session state are possible (see further) • Save only data (Dictionary) • An error is thrown if not serializable • By default, a class is not serializable!
When is a type serializable? • Your class must have the Serializable attribute • Any classes it derives from must have the Serializable attribute • All the member variables of the class must use serializable data types
DEMO ViewState and serialization ViewState with errors
Tip: save member variables • By default, member variables aren’t saved between requests private Dictionary<string, string> ControlText { get { if (ViewState["ControlText"] != null) { return (Dictionary<string, string>)ViewState["ControlText"]; } else { return new Dictionary<string, string>(); } } set {ViewState["ControlText"] = value;} }
Why not using ViewState? • You need to store mission-critical data • User could tamper with ViewState data • Session state is better for this type of data • You need to store information that will be used by multiple pages • Cookies might be better • You need to store an extremely large amount of information • ViewState is sent with every request, can slow down enormously! • Consider disabling it!
How to increase performance with ViewState • Disable it for controls that never change • A button • If the control is repopulated in every postback • Label that shows current time • Control is input control • ASP.NET will populate your input controls using the submitted form values after a postback <%@ Page Language="C#" EnableViewState="false" ... %>
ASP.NET 4.0 ViewState changes • Control.ViewStateMode • Enabled • Disabled • Inherit (default) • Control.ClientIdMode • Legacy • Static • Predictable • Inherit (default)
View State Security • ViewState is NOT SECURE! • Can be hacked in a matter of seconds • See demo! • 2 options • Hash codes • Encryption • Both use machineKey <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="dDw3NDg2NTI5MDg7Oz4="/>
View State Security • Hashcodes = a cryptographically strong checksum • A change of a hacker will be noticed by ASP.NET automatically • Enabled by default • Can be disabled • For example in a webfarm <%@ Page EnableViewStateMAC="false" ... %>
View State Security • Encryption • Can be set to Always, Never and Auto • Auto is when a user control requests it • Causes overhead • Only use when needed Auto is default <%@Page ViewStateEncryptionMode="Always" ... %> Page.RegisterRequiresViewStateEncryption()
DEMO Reading the ViewState
Problems... Nothing but problems... • ViewState is bound to one page • Web apps of one page are so 1995 • What does our ASP.NET bag-o-tricks have to solve this?
Transferring Information Between Pages • Query string • Portion of the URL after the question mark • Demo: search for my inner self ;-) • Pro: • Lightweight • No burden on the server • Con • Information is limited to simple strings • Information is clearly visible to the user • Send a password in the query string and be struck by lightning! • A user might decide to modify the query string and supply new values • Many browsers impose a limit on the length of a URL
Uses of the query string • Catalog application • Browse through items • Select an item • View detail • Detail page knows what you want to see more of based on parameter in query string
Using the Query String • You need to place the information there yourself • No collection-based approach for this • Mulitple parameters // Go to newpage.aspx. Submit a single query string argument // named recordID and set to 10. int recordID = 10; Response.Redirect("newpage.aspx?recordID=" + recordID.ToString()); // Go to newpage.aspx. Submit two query string arguments: // recordID (10) and mode (full). Response.Redirect("newpage.aspx?recordID=10&mode=full"); string ID = Request.QueryString["recordID"];
DEMO Query string
Cross-Page Posting • Different: it does not post to itself! • Simply post to another page, containing all the information from the original page • Even input values of controls • Potential problems: • Difficult to debug • Difficult to enhance • Tightly coupled pages • Works using the PostBackUrl property • Defined on IButtonControl • Implemented by Button, ImageButton... • PreviousPage has the properties you need
Cross-Page Posting <form id="form1" runat="server" > <div> <asp:TextBox runat="server" ID="txtFirstName"></asp:TextBox> <asp:TextBox runat="server" ID="txtLastName"></asp:TextBox> <asp:Button runat="server" ID="cmdSubmit" PostBackUrl="CrossPage2.aspx" Text="Submit" /> </div> </form>
Cross-Page Posting • What happens here? • On first access of Page.PreviousPage • ASP.NET runs page processing of Source page • Interrupts before PreRender • Catches all Response.Write and ignores them • All other events of the previous page are fired protected void Page_Load(object sender, EventArgs e) { if (PreviousPage != null) { lblInfo.Text = "You came from a page titled " + PreviousPage.Header.Title; } }
Getting Page-Specific Information • You may need more that just the Page members (which was what we had so far) • You need to cast to original type • Or include PreviousPageType protected void Page_Load(object sender, EventArgs e) { CrossPage1 prevPage = PreviousPage as CrossPage1; if (prevPage != null) { // (Read some information from the previous page.) } } <%@ PreviousPageType VirtualPath="CrossPage1.aspx" %>
Access other data on the Page • Controls are declared as protected • Either use controls • Too much info though • Better to restrict this public TextBox FirstNameTextBox { get { return txtFirstName; } } public TextBox LastNameTextBox { get { return txtLastName; } } public string FullName { get { return txtFirstName.Text + " " + txtLastName.Text; } }
Cross-Page Posting validation • When cross-posting, validation check is needed • Someone might have JS disabled and get to your second page without valid data // This code is in the target page. protected void Page_Load(object sender, EventArgs e) { // Check the validity of the previous page. if (PreviousPage != null) { if (!PreviousPage.IsValid) { // Display an error message or just do nothing. } else { ... } } }
IsPostBack and IsCrossPagePostBack • IsPostBack allows you to check if a page was posted back to itself • Allows you to skip heavy initialisation code • If you want to check if the page is executing because of a cross page postback, use IsCrossPagePostBack
IsCrossPagePostBack protected void Page_Load(object sender, EventArgs e) { if (IsCrossPagePostBack) { // This page triggered a postback to CrossPage2.aspx. // Don't perform time-consuming initialization unless it affects // the properties that the target page will read. } else if (IsPostBack) { // This page was posted back normally. // Don't do the first-request initialization. } else { // This is the first request for the page. // Perform all the required initialization. } }
DEMO Cross-page posting
Cookies • Small files that are created on the client’s hard drive • Pro • work transparently for user • Is not aware of cookies being used • Can be reused by several pages in your app • Long-term storage • Con • Simple string information • Human-readable Not a good choice for sensitive information • Some users disable cookies
Cookies • Classes are located in System.Net namespace • Request and Response have a cookie collection • Request is used to retrieve cookies • Response is used to attach cookies • Session state and Forms security use cookies implicitly
Creating cookies // Create the cookie object. HttpCookie cookie = new HttpCookie("Preferences"); // Set a value in it. cookie["LanguagePref"] = "English"; // Add another value. cookie["Country"] = "US"; // Add it to the current web response. Response.Cookies.Add(cookie); // This cookie lives for one year. cookie.Expires = DateTime.Now.AddYears(1);
Retrieving cookies • Deleting a cookie HttpCookie cookie = Request.Cookies["Preferences"]; // Check to see whether a cookie was found with this name. // This is a good precaution to take, // because the user could disable cookies, // in which case the cookie would not exist. string language; if (cookie != null) { language = cookie["LanguagePref"]; } HttpCookie cookie = new HttpCookie("LanguagePref"); cookie.Expires = DateTime.Now.AddDays(-1); Response.Cookies.Add(cookie);
DEMO I want a cookie!!!
Session state • Heavyweight of state management • Allows information to be stored in one page and accessed in another • Pro • All data types are possible to store • Collection-based like ViewState • Per-user session • Save for storing information like basket • All information is saved on the server • Con • More memory used on server • Small for 1 user, huge for big amount of users
Session state architecture • Session is not something from HTTP • Extra work for ASP.NET • Each session has a unique 120-bit identifier • ASP.NET uses algorithm to generate this value, thereby guaranteeing (statistically speaking) that the number is • unique • random enough so a malicious user can’t reverse-engineer or guess what session ID a client will be using • This ID will be sent over the wire • The only thing that will be sent actually!
Session state architecture • When receiving session ID • ASP.NET looks up corresponding session • retrieves the serialized data from the state server • converts it to live objects • places these objects into a special collection • This happens automagically ;)