How to move the ViewState from a hidden field on the client to a session on the server
This is a post relevant to all the developers out there that use Web Forms as their main ASP.Net platform.
In this post I would like to talk about ViewState and how we can move it and store it in a session on the server's memory. We know that the default hidden client field for ViewState can become very large on pages.That can problematic in terms of SEO and performance.
Let's talk a little bit about ViewState since not everybody knows what it is and why we need it. We need those state preserving mechanisms due to the fact that the web and HTTP in particular, are stateless.
ViewState represents the state of the page when it was last processed on the server. We use it to retain values across two successive requests for the same page. It is a hidden field added to the page and is restored on the server before the page request is processed. The Viewstate information travels back and forth with the page itself, but contains no visual elements that need to be rendered.
Have a look here and here to see two posts of mine talking about ViewState.If you want to see some other posts of mine that I talk about State mechanisms have a look here and here
I am going to create a simple website that retrieves data from a database using the well established Entity Framework ORM.
I will be using Entity Framework version 4.0 that ships with Visual
Studio 2010 and .Net 4.0.
We will create a simple website and use Entity Framework as our data access layer.
I assume that you have access to a version of SQL Server and AdventureWorkLT database.
If you do not, you can download and install the free SQL Server Express edition from here. If you need the installation scripts for the sample AdventureWorkLT database, click here
1) Launch Visual Studio 2010 (express edition will work fine). Create a new empty website and choose a suitable name for it. Choose C# as the development language.
2) Add a new item to your site, a web form. Leave the default name, Default.aspx
3) Add a new item to your site, a ADO.Net Entity Data model. Choose a suitable name for it, e.g AdventureWorkLT.edmx.
4) Then the Wizard pops up. Choose "Generate from Database". Have a look at the picture below
5) Click Next and Create a New Connection (as you see in the picture below) and hit the Continue button.
6) Then follow the instructions as shown in the picture below.Select the local installation of your SQL Server and the database name and then click OK.
7) After you complete the steps above you will see something like the picture below. You can see the Entity connection string and where these setting will be saved.Hit the Next button.Then click Finish
8) Now the wizard will identify the database objects and let us choose which database objects we want to include in our model.I included all the database objects.Hit the Finish button.
9) Have a look at your entity model as it is visualized in the Entity Model Designer. Have a look at the Entity classes and their relationships/associations.Have a look at the properties of each Entity class. Have also a look at the Navigation Properties of each entity class.Basically the entity framework generates classes for all the entities in the designer. You can have a look at the generated code if you want by opening the class file, which in my case is AdvWorks.Designer.cs.
10) Now we are ready to start querying our database. We will issue a Linq to Entities query against the conceptual schema.
Let's create a new query and bind the resultset to a GridView control. Add a GridView control to the default.aspx page.
In this query we want to get only the customers that have more than one order and the Title equals "Ms"
If you are not so familiar with Linq queries, have a look at my other posts in this blog regarding LINQ.
In the Page_Load event handling routine type:
AdventureWorksLTEntities ctx = new AdventureWorksLTEntities();
var query = from mycust in ctx.Customers
join sho in ctx.SalesOrderHeaders on mycust.CustomerID
equals sho.CustomerID
into myorders
where (mycust.Title=="Ms." && mycust.SalesOrderHeaders.Count >= 1)
select new { mycust.FirstName, mycust.LastName,OrdersCount =
myorders.Count() };
GridView1.DataSource = query;
GridView1.DataBind();
Do not forget to add this as well in .cs file
using AdventureWorksLTModel;
11) Run your application and you will see the results.
12) Have a look at the View Source of your page and see the ViewState hidden field.You will see a large hidden field with lots of encoded data in it. We need to move it from the client (the browser will not have to download it) and store it on the server's memory where RAM is not an issue.Have a look at the picture below
13) Now let's see how we can accomplish that.I am going to use an Adapter which is basically a class file. Add another class file in the App_Code special folder.Name it ServerSideViewStateAdapter.cs.
The code for the .cs file follows
public class ServerSideViewStateAdapter:PageAdapter { public override PageStatePersister GetStatePersister() { return new SessionPageStatePersister(this.Page); } }
Let me explain what the code above does.I have my newly created class that needs to implement the PageAdapter class.
There is a method in that class called GetStatePersister that returns the SessionPageStatePersister that stores ASP.Net page view state on the web server.
You can read more here.
Do not to forget to use in your code the two namespaces
using System.Web.UI.Adapters; using System.Web.UI;
14) Now we need to configure the Adapter. We need to add a new special folder to our site, a App_Browsers folder. Add a new item to this special folder,a .browser file and name it ViewStateAdapter.browser.
The code inside this file follows
<browsers> <browser refID="Default"> <controlAdapters> <adapter controlType="System.Web.UI.Page" adapterType ="ServerSideViewStateAdapter"> </adapter> </controlAdapters> </browser> </browsers>
I define that this Adapter (that I have already created) will target all browsers ( <browser refID="Default">)
15) Now that you have everything configured, view the page on the browser again. You will have the same results. Look now in the Page --> View Source and you will see that the ViewState has been removed and there is only a simple key now present.If I had huge ViewState info in my page by using this technique my clients would download much less client code. My website's responsiveness and performance would significantly increase.
Have a look at the picture below to see what I actually mean.
Having said all that I would like to mention once more that you can disable ViewState at application,page and control level.
If you go to your web.config file you can disable it for the whole application
<pages enableViewState-"false" />
You can disable it on page level inside the Page directive
<%@ Page EnableViewState = "false" %>
and you can also disable it on each individual control
<asp:Button id="mybutton" runat="server" EnableViewState="false" />
Drop me an email if you need the source code.
Hope it helps!!