![]() |
Web Development »
ASP.NET »
General
Intermediate
Manage ViewState using ASP.NET 2.0 Provider ArchitectureBy Oleg SobolServerSide ViewState management using custom providers based on ASP.NET 2.0 provider pattern architecture. |
VB 8.0.NET 2.0, Win2K, WinXP, Win2003, Vista, ASP.NET, WebForms, SQL 2005, VS2005, Architect, DBA, Dev
|
||||||||||
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
This article shows an implementation of a couple of custom viewstate providers using ASP.NET 2.0 Provider architecture and the Provider Model design pattern. To get more information regarding the ASP.NET 2.0 Provider Model please read Introduction to the Provider Model
About half a year ago I was working on a project that required moderately large datasets fetched from the database and displayed in a datagrid. Going to the database on every postback seemed like a waste of resources, therefore, I decided to store the data in viewstate. And thats when the page load times started taking longer and longer. I started researching alternative solutions for optimizing viewstate and found a moderate amount of information and examples online. Nevertheless, I have not been able to find a complete solution that would let me easily manage and extend the functionality of viewstate without having to make significant changes to the website.
I have looked at a number of interesting and useful articles that provided different takes on the implementation of the viewstate management, but none had a complete and easily integrable solution.
The code presented below was inspired by or partially taken from the following articles:
I will concentrate on describing just the viewstate provider code without going into details on the provider pattern design. For detailed explanation of pattern design and architecture please see references listed above.
First, we need an abstract class representing the viewstate and exposing functions actual providers will implement. ViewStateProvider is derived from ProviderBase
and will be the base class for all concrete viewstate provider classes.
It will have two functions that must be implemented by derived classes:
LoadPageState and SavePageState.
''' <summary>
''' Defines the contract that ASP.NET implements to provide viewstate
''' services using custom viewstate providers.
''' </summary>
Public MustInherit Class ViewStateProvider
Inherits System.Configuration.Provider.ProviderBase
Public MustOverride Property ApplicationName() As String
''' <summary>
''' The hidden field variable name where our viewstate reference key is stored on a page.
''' </summary>
Public MustOverride Property ViewStateKeyName() As String
''' -----------------------------------------------------------------------------
''' <summary>
''' Loads any saved view-state of the current page from virtually any
''' storage medium other than a hidden field
''' </summary>
''' <param name="pControl">System.Web.UI.Page</param>
''' <returns>The saved view state</returns>
''' -----------------------------------------------------------------------------
Public MustOverride Function LoadPageState(ByVal pControl As Control) As Object
''' -----------------------------------------------------------------------------
''' <summary>
''' Saves any view-state information of the page to virtually any
''' storage medium other than a hidden field
''' </summary>
''' <param name="pControl">System.Web.UI.Page</param>
''' <param name="viewState">A System.Object in which to store the view-state information</param>
''' -----------------------------------------------------------------------------
Public MustOverride Sub SavePageState(ByVal pControl As Control, ByVal viewState As Object)
End Class
Next, we need an actual provider class. I have three concrete provider classes in the example:
SessionViewStateProvider- - viewstate is being maintained as a session variable.
CompressionViewStateProvider- - viewstate is being compressed using ICSharpCode.SharpZipLib and written to a page.
SqlViewStateProvider- - viewstate is maintained using a modified ASPState database. The ViewState is written to the database similar to an OutOfProc Session.
Lets look at one of them - SessionViewStateProvider.
NOTE:
This provider requires sql script attached with the code to be executed
on the database where the viewstate will be stored. Proper sql
connection and impersonation must be set up in Web.config. All of the
sql script code is taken from Adam Weigert's SqlViewState - The Path To Better ViewState Storage.
Other providers in the example do not require any additional setup except registration in a Web.config(explained here).
''' <summary>
''' Manages storage of viewstate object for an ASP.NET application in a SQL Server database.
''' </summary>
''' <remarks><para><pre>
''' RevisionHistory:
''' --------------------------------------------------------------------------------
''' Date Name Description
''' --------------------------------------------------------------------------------
''' 10/11/2006 Oleg Sobol Initial Creation
''' inspiration taken from
''' http://weblogs.asp.net/adweigert/archive/2004/03/09/sqlviewstate-the-path-to-better-viewstate-storage.aspx
''' 5/11/2007 Oleg Sobol Added ViewStateKeyName and DEFAULT_TIMEOUT
''' </pre></para></remarks>
Public Class SqlViewStateProvider
Inherits System.Web.UI.ViewStateProvider
Public Const DEFAULT_TIMEOUT As Integer = 25
Private _applicationName As String
Private _connectionString As String
Private _connectionStringName As String
Private _timeout As TimeSpan
Private _enableViewStateMac As Boolean
Private _lockLoad As New Object
Private _lockSave As New Object
Private _viewStateKeyName As String = "__VIEWSTATE_KEY"
Public Overloads Overrides Property ApplicationName() As String
Get
Return _applicationName
End Get
Set(ByVal value As String)
_applicationName = value
End Set
End Property
Public Property ConnectionStringName() As String
Get
Return _connectionStringName
End Get
Set(ByVal value As String)
_connectionStringName = value
End Set
End Property
Public Property Timeout() As TimeSpan
Get
Return _timeout
End Get
Set(ByVal value As TimeSpan)
_timeout = value
End Set
End Property
Public Property EnableViewStateMac() As Boolean
Get
Return _enableViewStateMac
End Get
Set(ByVal value As Boolean)
_enableViewStateMac = value
End Set
End Property
Public Overrides Property ViewStateKeyName() As String
Get
Return _viewStateKeyName
End Get
Set(ByVal value As String)
_viewStateKeyName = value
End Set
End Property
Public Overloads Overrides Sub "init">Initialize(ByVal name As String, ByVal config As NameValueCollection)
' Verify that config isn't null
If config Is Nothing Then Throw New ArgumentNullException("config")
' Assign the provider a default name if it doesn't have one
If String.IsNullOrEmpty(name) Then name = "SqlViewStateProvider"
' Add a default "description" attribute to config if the attribute doesn't exist or is empty
If String.IsNullOrEmpty(config("description")) Then
config.Remove("description")
config.Add("description", "SQL viewstate provider")
End If
' Call the base class's Initialize method
MyBase.Initialize(name, config)
' Initialize _applicationName
_applicationName = config("applicationName")
If String.IsNullOrEmpty(_applicationName) Then _applicationName = "/"
config.Remove("applicationName")
Dim connect As String = config("connectionStringName")
If String.IsNullOrEmpty(connect) Then
Throw New ViewStateProviderException("Empty or missing connectionStringName")
End If
config.Remove("connectionStringName")
If WebConfigurationManager.ConnectionStrings(connect) Is Nothing Then
Throw New ViewStateProviderException("Missing connection string")
End If
_connectionString = WebConfigurationManager.ConnectionStrings(connect).ConnectionString
If String.IsNullOrEmpty(_connectionString) Then
Throw New ViewStateProviderException("Empty connection string")
End If
Dim timeout As String = config("timeout")
If String.IsNullOrEmpty(timeout) OrElse Not IsNumeric(timeout) Then
_timeout = TimeSpan.FromMinutes(ViewStateProvidersConfig.DefaultViewStateTimeout)
Else
_timeout = TimeSpan.FromMinutes(CInt(timeout))
End If
config.Remove("timeout")
Dim enableViewStateMac As String = config("enableViewStateMac")
Try
_enableViewStateMac = CBool(enableViewStateMac)
Catch ex As Exception
_enableViewStateMac = False
End Try
config.Remove("enableViewStateMac")
' Throw an exception if unrecognized attributes remain
If config.Count > 0 Then
Dim attr As String = config.GetKey(0)
If Not String.IsNullOrEmpty(attr) Then _
Throw New ViewStateProviderException("Unrecognized attribute: " + attr)
End If
End Sub
Public Overrides Function LoadPageState(ByVal pControl As System.Web.UI.Control) As Object
Dim connection As SqlConnection = Nothing
Dim rawData As Byte() = Nothing
Dim stream As MemoryStream = Nothing
Try
Dim viewStateGuid As Guid = GetViewStateGuid(pControl)
connection = New SqlConnection(_connectionString)
Dim command As SqlCommand = New SqlCommand("GetViewState", connection)
Try
command.CommandType = CommandType.StoredProcedure
command.Parameters.Add("@returnValue", SqlDbType.Int).Direction = ParameterDirection.ReturnValue
command.Parameters.Add("@viewStateId", SqlDbType.UniqueIdentifier).Value = viewStateGuid
connection.Open()
Dim reader As SqlDataReader = command.ExecuteReader
Try
If reader.Read Then
rawData = CType(Array.CreateInstance(GetType(Byte), reader.GetInt32(0)), Byte())
End If
If reader.NextResult AndAlso reader.Read Then
reader.GetBytes(0, 0, rawData, 0, rawData.Length)
End If
Catch e As Exception
Throw New ViewStateProviderException("Problem reading data returned from SqlServer", e)
Finally
CType(reader, IDisposable).Dispose()
End Try
Catch e As Exception
Throw New ViewStateProviderException("Problem executing SqlCommand", e)
Finally
If Not command Is Nothing Then command.Dispose()
End Try
Catch e As Exception
Throw New ViewStateProviderException("Problem with SqlConnection", e)
Finally
If Not connection Is Nothing Then connection.Dispose()
End Try
Try
stream = New MemoryStream(rawData)
Return Me.GetLosFormatter(pControl, False).Deserialize(stream)
Catch e As Exception
Throw New ViewStateProviderException("Problem with data deserialization", e)
Finally
If Not stream Is Nothing Then CType(stream, IDisposable).Dispose()
End Try
Return Nothing
End Function
Public Overrides Sub SavePageState(ByVal pControl As System.Web.UI.Control, ByVal viewState As Object)
Dim p As Page = Nothing
Dim viewStateGuid As Guid
Dim stream As MemoryStream = Nothing
Try
p = CType(pControl, Page)
viewStateGuid = GetViewStateGuid(p)
stream = New MemoryStream
GetLosFormatter(p, _enableViewStateMac).Serialize(stream, viewState)
Dim connection As SqlConnection = New SqlConnection(_connectionString)
Try
Dim command As SqlCommand = New SqlCommand("SetViewState", connection)
Try
command.CommandType = CommandType.StoredProcedure
command.Parameters.Add("@returnValue", SqlDbType.Int).Direction _
= ParameterDirection.ReturnValue
command.Parameters.Add("@viewStateId", SqlDbType.UniqueIdentifier).Value = viewStateGuid
command.Parameters.Add("@value", SqlDbType.Image).Value = stream.ToArray
command.Parameters.Add("@timeout", SqlDbType.Int).Value = _timeout.TotalMinutes
connection.Open()
command.ExecuteNonQuery()
Catch e As Exception
System.Diagnostics.Trace.Write(e.Message)
Finally
If Not command Is Nothing Then command.Dispose()
End Try
Catch e As Exception
System.Diagnostics.Trace.Write(e.Message)
Finally
If Not connection Is Nothing Then connection.Dispose()
End Try
Catch e As Exception
System.Diagnostics.Trace.Write(e.Message)
Finally
If Not stream Is Nothing Then CType(stream, IDisposable).Dispose()
End Try
Dim control As Html.HtmlInputHidden _
= CType(p.FindControl(ViewStateProvidersConfig.ViewStateKeyFieldName), Html.HtmlInputHidden)
If control Is Nothing Then
p.ClientScript.RegisterHiddenField(ViewStateProvidersConfig.ViewStateKeyFieldName, _
viewStateGuid.ToString)
Else
control.Value = viewStateGuid.ToString
End If
End Sub
#Region " Private Helper Functions "
Private Function GetViewStateGuid(ByVal pControl As Control) As Guid
Dim p As Page = CType(pControl, Page)
Dim viewStateKey As String = p.Request.Form(ViewStateProvidersConfig.ViewStateKeyFieldName)
If viewStateKey Is Nothing OrElse viewStateKey.Length < 1 Then
viewStateKey = p.Request.QueryString(ViewStateProvidersConfig.ViewStateKeyFieldName)
If viewStateKey Is Nothing OrElse viewStateKey.Length < 1 Then
Return Guid.NewGuid
End If
End If
Try
Return New Guid(viewStateKey)
Catch e As FormatException
Return Guid.NewGuid
End Try
End Function
Private Function GetMacKeyModifier(ByVal pControl As Control) As String
Dim p As Page = CType(pControl, Page)
Dim value As Integer = p.TemplateSourceDirectory.GetHashCode + Me.GetType.Name.GetHashCode
If Not (p.ViewStateUserKey Is Nothing) Then
Return String.Concat(value.ToString(NumberFormatInfo.InvariantInfo), p.ViewStateUserKey)
End If
Return value.ToString(NumberFormatInfo.InvariantInfo)
End Function
Private Function GetLosFormatter(ByVal pControl As Control, ByVal enableViewStateMac As Boolean) _
As LosFormatter
If enableViewStateMac Then Return New LosFormatter(True, GetMacKeyModifier(CType(pControl, Page)))
Return New LosFormatter
End Function
#End Region
End Class
SessionViewStateProvider's Initialize method expects to find a configuration attribute named ConnectionStringName identifying a connection string in the <connectionStrings> configuration section. The connection string is used by LoadPageState and SavePageState methods to load/save the viewstate string from/to the database.
Other properties include:
ApplicationName which gets populated from applicationName attribute.
ViewStateKeyName property will contain
the name of the hidden field where the reference to the viewstate will be kept on the page.
This reference cannot be kept in default __VIEWSTATE field, because it gets overwritten by Asp.Net rendering engine.
Timeout
property which sets the time in minutes for how long the database
should keep the current viewstate record. A SqlServer job runs every so
often and deletes all expired viewstate records from the table.
SavePageState serializes the viewState object passed into it using System.Web.UI.LosFormatter.
Creates a GUID to serve as a unique identifier, and saves the record in
a database. The newly generated GUID is then saved in a hidden field
variable of a page.LoadPageState retrieves the GUID from the hidden variable and gets viewState from the database.
Viewstate provider requires the following be added to the Web.config of the Web Application:
<configuration>
<configSections>
<sectionGroup name="system.web">
<section name="viewstate" type="System.Web.UI.ViewStateSection, CustomProviders"
restartOnExternalChanges="true" allowDefinition="MachineToApplication" />
</sectionGroup>
</configSections>
<connectionStrings>
<add name="ViewStateConnectionString"
connectionString="Server=(local);Database=ASPState;Integrated Security=True;" />
</connectionStrings>
<system.web>
<viewstate defaultProvider="CompressionViewStateProvider" enabled="true">
<providers>
<add name="SqlViewStateProvider" type="System.Web.Configuration.Providers.SqlViewStateProvider,
CustomViewStateProviders" connectionStringName="ViewStateConnectionString" timeout="35" />
<add name="SessionViewStateProvider"
type="System.Web.Configuration.Providers.SessionViewStateProvider,
CustomViewStateProviders" numberOfPagesInMemory="10" />
<add name="CompressionViewStateProvider"
type="System.Web.Configuration.Providers.CompressionViewStateProvider, CustomViewStateProviders" />
</providers>
</viewstate>
<system.web>
</configuration>
Since viewstate is not a stock configuration section, a custom
configuration section must be written that derives from
System.Configuration.ConfigurationSection. The following is a System.Web.UI.ViewStateSection class that exposes two properties: Providers and DefaultProvider. The <ConfigurationProperty> attributes map ViewStateSection
properties to <viewstate> attributes in a configuration file. As
a result, the DefaultProvider property will get its value from
<viewstate> element's defaultProvider attribute, if present, and
so on.
''' <summary>
''' Maps to a <viewstate> section in a configuration file
''' </summary>
Public Class ViewStateSection
Inherits ConfigurationSection
<ConfigurationProperty("providers")> Public ReadOnly Property Providers() As ProviderSettingsCollection
Get
Return CType(MyBase.Item("providers"), ProviderSettingsCollection)
End Get
End Property
<ConfigurationProperty("defaultProvider"), DefaultSettingValue("")> _
Public Property DefaultProvider() As String
Get
Return CStr(MyBase.Item("defaultProvider"))
End Get
Set(ByVal value As String)
MyBase.Item("defaultProvider") = value
End Set
End Property
End Class
Below is the way our custom section is registered with ASP.NET to be inside system.web section of a configuration file. NOTE: type="System.Web.UI.ViewStateSection, CustomProviders" has the namespace.class and assembly name in which the class is located.
<configSections>
<sectionGroup name="system.web">
<section name="viewstate" type="System.Web.UI.ViewStateSection, CustomProviders"
restartOnExternalChanges="true" allowDefinition="MachineToApplication" />
</sectionGroup>
</configSections>
At last we need a class that will load and manage all viewstate providers registered in Web.config. ViewStateManager
class will be used in actual aspx pages to load/save the viewstate. It
will contain a collection of all providers registered in Web.config,
with one of them set as default provider.
''' <summary>
''' Manages all viewstate manipulations.
''' </summary>
Public Class ViewStateManager
Private Shared _provider As ViewStateProvider = Nothing
Private Shared _providers As ViewStateProviderCollection = Nothing
Private Shared _lock As New Object
Private Shared _enabled As Boolean
Private Shared _enabledSet As Boolean
''' <summary>
''' Default provider set in web.config
''' </summary>
Public Shared ReadOnly Property Provider() As ViewStateProvider
Get
Return _provider
End Get
End Property
Public Shared ReadOnly Property Providers() As ViewStateProviderCollection
Get
Return _providers
End Get
End Property
Public Shared ReadOnly Property Enabled() As Boolean
Get
If Not _enabledSet Then
_enabled = GetViewStateSection().Enabled
_enabledSet = True
End If
Return _enabled
End Get
End Property
Shared Sub New()
Call LoadProviders()
End Sub
Public Shared Function LoadPageState(ByVal pControl As Control) As Object
' Make sure a provider is loaded
Call LoadProviders()
' Delegate to the provider
Return _provider.LoadPageState(pControl)
End Function
Public Shared Sub SavePageState(ByVal pControl As Control, ByVal viewState As Object)
' Make sure a provider is loaded
Call LoadProviders()
' Delegate to the provider
_provider.SavePageState(pControl, viewState)
End Sub
Private Shared Sub LoadProviders()
' Avoid claiming lock if providers are already loaded
If _provider Is Nothing Then
SyncLock _lock
' Do this again to make sure _provider is still null
If _provider Is Nothing Then
' Get a reference to the <viewstate> section
Dim section As ViewStateSection = GetViewStateSection()
' Is custom viewstate management enabled
If section IsNot Nothing Then _enabled = section.Enabled
_enabledSet = True
If _enabled Then
' Load registered providers and point _provider to the default provider
_providers = New ViewStateProviderCollection
ProvidersHelper.InstantiateProviders(section.Providers, _providers, _
GetType(ViewStateProvider))
_provider = _providers(section.DefaultProvider)
If _provider Is Nothing Then
Throw New ViewStateProviderException("Unable to load default ViewStateProvider")
End If
End If
End If
End SyncLock
End If
End Sub
Private Shared Function GetViewStateSection() As ViewStateSection
Return CType(WebConfigurationManager.GetSection("system.web/viewstate"), ViewStateSection)
End Function
End Class
</viewstate>
Inside LoadProviders, ProvidersHelper.InstantiateProviders subroutine loops through the viewstate/providers section under system.web in Web.Config and loads registered providers. It looks at the following to load a provider:
<add name="SqlViewStateProvider" type="System.Web.Configuration.Providers.SqlViewStateProvider,
CustomViewStateProviders" connectionStringName="ViewStateConnectionString" timeout="35" />
Now we need to overload the functions exposed by the Page class to
use our viewstate manager to save/load the viewstate. In the example
this is done by deriving a PageTemplate class that inherits from System.Web.UI.Page, and making all aspx pages inherit from the PageTemplate. PageTemplate has the following exposed besides the overriden viewstate functions:
ServerSideViewState - set to false to use regular page viewstate. This property can be set in a Web.config or in page's Init method. SetServerSideViewStateProvider - sets provider to be used on a page. This is a hack I used to enable using different provider on per page basis. defaultProvider
property in Web.config to set the provider for the whole application.
Using SetServerSideViewStateProvider could get messy fast and is not a best practice in my opinion.
Below is the proper code for the overloaded page. The code in the example will differ slightly to show different implementations on per page basis.
Protected Overloads Overrides Function LoadPageStateFromPersistenceMedium() As Object
If _serverSideViewState AndAlso ViewStateManager.Enabled Then
Return ViewStateManager.LoadPageState(Me)
Else
Return MyBase.LoadPageStateFromPersistenceMedium ' regular client viewState
End If
End Function
Protected Overloads Overrides Sub SavePageStateToPersistenceMedium(ByVal viewState As Object)
If _serverSideViewState AndAlso ViewStateManager.Enabled Then
ViewStateManager.SavePageState(Me, viewState)
Else
MyBase.SavePageStateToPersistenceMedium(viewState) ' regular client viewState
End If
End Sub
Anthem.Net is, in my opinion, the best AJAX library out to date. And it would be a shame if it couldn't be used in conjunction with CustomViewState implementation. To read more on Anthem.Net please see Introduction to Anthem.NET.
NOTE: This solution will always use the default viewstate provider set in web.config. Setting provider on per page basis usingSetServerSideViewStateProvider property will be ignored.
Because Anthem is managing outputting ViewState to the page separately from Asp.Net, we need to make Anthem write our
hidden variable with the ViewStateKeyName to the page if it exists.
Retrieval and loading of viewstate will be handled by Asp.Net as the normal page lifecycle is started by Anthem during
a callback.
To integrate ViewStateManager we need to make the following modifications in Anthem project:
private string GetServerSideViewState(string html)
{
if (ViewStateManager.Enabled) {
return GetHiddenInputValue(html, "<input type=\"hidden\" name=\"" +
ViewStateManager.Provider.ViewStateKeyName + "\" id=\"" +
ViewStateManager.Provider.ViewStateKeyName + "\" value=\"");
}
else {
return null;
}
}
WriteValueAndError function in Manager.cs, which will
add values including updated serverSideViewState variable to the response string to be written back to the page
/// <summary>
/// Adds ServerSideViewState support
/// </summary>
private static void WriteValueAndError(
StringBuilder sb,
object val,
string error,
string viewState,
string viewStateEncrypted,
string serverSideViewState,
string serverSideViewStateKey,
string eventValidation,
Hashtable controls,
string[] scripts)
{
sb.Append("{\"value\":");
WriteValue(sb, val);
sb.Append(",\"error\":");
WriteValue(sb, error);
if (viewState != null)
{
sb.Append(",\"viewState\":");
WriteValue(sb, viewState);
}
if (viewStateEncrypted != null)
{
sb.Append(",\"viewStateEncrypted\":");
WriteValue(sb, viewStateEncrypted);
}
if (serverSideViewState != null)
{
sb.Append(",\"serverSideViewState\":");
WriteValue(sb, serverSideViewState);
}
if (serverSideViewStateKey != null)
{
sb.Append(",\"serverSideViewStateKey\":");
WriteValue(sb, serverSideViewStateKey);
}
if (eventValidation != null)
{
sb.Append(",\"eventValidation\":");
WriteValue(sb, eventValidation);
}
if (controls != null && controls.Count > 0)
{
sb.Append(",\"controls\":{");
foreach (DictionaryEntry control in controls)
{
sb.Append("\"" + control.Key + "\":");
WriteValue(sb, control.Value);
sb.Append(",");
}
--sb.Length;
sb.Append("}");
}
if (scripts != null && scripts.Length > 0)
{
sb.Append(",\"pagescript\":[");
foreach (string script in scripts)
{
WriteValue(sb, script);
sb.Append(",");
}
--sb.Length;
sb.Append("]");
}
if (GetManager()._clientSideEvalScripts.Count > 0)
{
sb.Append(",\"script\":[");
foreach (string script in GetManager()._clientSideEvalScripts)
{
WriteValue(sb, script);
sb.Append(",");
}
--sb.Length;
sb.Append("]");
}
sb.Append("}");
}
WriteResult(Stream stream, MemoryStream htmlBuffer) function in Manager.cs to
integrate CustomViewState. This function sends the result string back to the page.
Modifications are shown in bold.
internal void WriteResult(Stream stream, MemoryStream htmlBuffer)
{
string viewState = null;
string serverSideViewState = null;
string viewStateEncrypted = null;
string eventValidation = null;
Hashtable controls = null;
string[] scripts = null;
if (_updatePage)
{
string html = HttpContext.Current.Response.ContentEncoding.GetString(htmlBuffer.GetBuffer());
viewState = GetViewState(html);
serverSideViewState = GetServerSideViewState(html);
#if V2
viewStateEncrypted = GetViewStateEncrypted(html);
eventValidation = GetEventValidation(html);
#endif
controls = GetControls(html);
foreach (object o in _targets.Values)
{
Control c = o as Control;
if (c != null && !c.Visible)
{
if (c.ID != null && controls.ContainsKey(c.ID))
controls[c.ID] = "";
}
}
scripts = GetScripts(html);
}
StringBuilder sb = new StringBuilder();
try
{
// If the serverSideViewState is null, that means CustomViewState is turned off on the page,
// and thus will be ignored inside WriteValueAndError.
// But we will double check for it here anyways.
if (ViewStateManager.Enabled && serverSideViewState != null) {
WriteValueAndError(sb, _value, _error, viewState, viewStateEncrypted,
serverSideViewState, ViewStateManager.Provider.ViewStateKeyName, eventValidation, controls, scripts);
}
else {
WriteValueAndError(sb, _value, _error, viewState, viewStateEncrypted, eventValidation, controls, scripts);
}
}
catch (Exception ex)
{
// If an exception was thrown while formatting the
// result value, we need to discard whatever was
// written and start over with nothing but the error
// message.
sb.Length = 0;
WriteValueAndError(sb, null, ex.Message, null, null, null, null, null);
}
// If an IOFrame was used to make this callback, then wrap the response in a <textarea> element
// so the iframe will not mess with the text of the JSON object.
string response = sb.ToString();
if (string.Compare(HttpContext.Current.Request["Anthem_IOFrame"], "true", true) == 0)
{
response = "<textarea id=\"response\">" + response + "</textarea>";
}
byte[] buffer = HttpContext.Current.Response.ContentEncoding.GetBytes(response);
stream.Write(buffer, 0, buffer.Length);
}
function Anthem_UpdatePage(result) {
var form = Anthem_GetForm();
if (result.viewState) {
Anthem_SetHiddenInputValue(form, "__VIEWSTATE", result.viewState);
}
if (result.serverSideViewState && result.serverSideViewStateKey) {
Anthem_SetHiddenInputValue(form, result.serverSideViewStateKey, result.serverSideViewState);
}
if (result.viewStateEncrypted) {
Anthem_SetHiddenInputValue(form, "__VIEWSTATEENCRYPTED", result.viewStateEncrypted);
}
if (result.eventValidation) {
Anthem_SetHiddenInputValue(form, "__EVENTVALIDATION", result.eventValidation);
}
if (result.controls) {
for (var controlID in result.controls) {
var containerID = "Anthem_" + controlID.split("$").join("_") + "__";
var control = document.getElementById(containerID);
if (control) {
control.innerHTML = result.controls[controlID];
if (result.controls[controlID] == "") {
control.style.display = "none";
} else {
control.style.display = "";
}
}
}
}
if (result.pagescript) {
Anthem_LoadPageScript(result, 0);
}
}
That's it. ServerSide viewstate makes Anthem noticeably more responsive. Check it out for yourself!
This code has been written but unfortunately never been tested in a real life application. Very interested to see SqlViewStateProvider
and other providers get used in a large scale application with a high
usage. Any ideas or other provider(better) implementations? All
feedback is most welcome.
| You must Sign In to use this message board. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 5 Jun 2007 Editor: |
Copyright 2007 by Oleg Sobol Everything else Copyright © CodeProject, 1999-2009 Web21 | Advertise on the Code Project |