2016-08-03 10:59:49 +00:00
//------------------------------------------------------------------------------
// <copyright file="SessionViewState.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System ;
using System.Collections ;
using System.Diagnostics ;
using System.ComponentModel ;
using System.Globalization ;
using System.IO ;
using System.Runtime.Serialization ;
using System.Text ;
using System.Web ;
using System.Web.SessionState ;
using System.Web.Util ;
using System.Web.UI ;
using System.Security.Permissions ;
namespace System.Web.UI.MobileControls
{
/ *
* Session - based view state .
*
* When saving view state on the server as session data , some critical problems
* arise . The core issue behind most of these is how to handle the user
* clicking the Back button . When the user does this , there is no corresponding
* notification to the server , and the client and server session state are thrown
2017-08-21 15:34:15 +00:00
* out of sync .
2016-08-03 10:59:49 +00:00
*
* This class attempts to alleviate this by storing a small history of view states
* in session data .
*
* To save session view state , construct a new object , set the ViewState and ActiveForm
* properties , and call Save . You ' ll get back a reference that contains the
* state reference to write out .
*
* To load session view state , construct a new object , and call Load . The class will
* attempt to construct the view state from its history .
*
* Copyright ( c ) 2000 Microsoft Corporation
* /
[Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
internal class SessionViewState
{
private static readonly String ViewStateKey = "ViewState" ;
private Object _state ;
internal SessionViewState ( ) {
}
internal /*public*/ Object ViewState
{
get
{
return _state ;
}
set
{
_state = value ;
}
}
internal /*public*/ Pair Save ( MobilePage page )
{
SessionViewStateHistory history = ( SessionViewStateHistory ) page . Session [ ViewStateKey ] ;
if ( history = = null )
{
history = new SessionViewStateHistory ( HttpContext . Current ) ;
page . Session [ ViewStateKey ] = history ;
}
SessionViewStateHistoryItem historyItem = new SessionViewStateHistoryItem ( ) ;
SaveTo ( historyItem ) ;
#if TRACE
historyItem . Url = page . Request . FilePath ;
#endif
return history . Push ( historyItem ) ;
}
internal /*public*/ void Load ( MobilePage page , Pair id )
{
_state = null ;
SessionViewStateHistory history = ( SessionViewStateHistory ) page . Session [ ViewStateKey ] ;
if ( history ! = null )
{
SessionViewStateHistoryItem historyItem = history . Find ( id ) ;
if ( historyItem ! = null )
{
LoadFrom ( historyItem ) ;
}
}
}
private void SaveTo ( SessionViewStateHistoryItem historyItem )
{
historyItem . ViewState = _state ;
}
private void LoadFrom ( SessionViewStateHistoryItem historyItem )
{
_state = historyItem . ViewState ;
}
#if TRACE
internal /*public*/ void Dump ( MobilePage page , out ArrayList arr )
{
SessionViewStateHistory history ;
if ( ( page is IRequiresSessionState ) & & ! ( page is IReadOnlySessionState ) )
{
history = ( SessionViewStateHistory ) page . Session [ ViewStateKey ] ;
}
else
{
history = null ;
}
if ( history ! = null )
{
history . Dump ( out arr ) ;
}
else
{
arr = new ArrayList ( ) ;
}
}
#endif
[
Serializable
]
private class SessionViewStateHistoryItem : ISerializable
{
#if TRACE
public String Url ;
public String Id ;
#endif
public Object ViewState ;
public SessionViewStateHistoryItem ( )
{
}
public SessionViewStateHistoryItem ( SerializationInfo info , StreamingContext context )
{
String s = ( String ) info . GetString ( "s" ) ;
if ( s . Length > 0 )
{
ViewState = new LosFormatter ( ) . Deserialize ( s ) ;
}
else
{
ViewState = null ;
}
}
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter=true)]
void ISerializable . GetObjectData ( SerializationInfo info , StreamingContext context )
{
if ( ViewState ! = null )
{
StringWriter s = new StringWriter ( CultureInfo . InvariantCulture ) ;
new LosFormatter ( ) . Serialize ( s , ViewState ) ;
info . AddValue ( "s" , s . ToString ( ) ) ;
}
else
{
info . AddValue ( "s" , String . Empty ) ;
}
}
}
// Session view state history. This is the history record kept in each session.
[
Serializable
]
private class SessionViewStateHistory
{
private int _historySize ;
private SessionViewStateHistoryItem [ ] _history ;
private int _currentHistoryIndex = 0 ;
private int _historyUsed = 0 ;
private DateTime _sessionUniqueID = DateTime . Now ;
private int _currentHistoryID = 0 ;
public SessionViewStateHistory ( HttpContext context )
{
_historySize = ControlsConfig . GetFromContext ( context ) . SessionStateHistorySize ;
if ( _historySize < 1 )
{
throw new Exception (
SR . GetString ( SR . SessionViewState_InvalidSessionStateHistory ) ) ;
}
_history = new SessionViewStateHistoryItem [ _historySize ] ;
}
public Pair Push ( SessionViewStateHistoryItem item )
{
Pair id = new Pair ( _sessionUniqueID , _currentHistoryID ) ;
_currentHistoryID + + ;
_history [ _currentHistoryIndex ] = item ;
_currentHistoryIndex = ( _currentHistoryIndex + 1 ) % _historySize ;
if ( _historyUsed < _historySize )
{
_historyUsed + + ;
}
#if TRACE
item . Id = _currentHistoryID . ToString ( CultureInfo . InvariantCulture ) ;
#endif
return id ;
}
public SessionViewStateHistoryItem Find ( Pair id )
{
// First make sure that the page is from the current session.
DateTime uniqueID = ( DateTime ) id . First ;
if ( DateTime . Compare ( uniqueID , _sessionUniqueID ) ! = 0 )
{
return null ;
}
// Now check if we actually still have it.
int historyID = ( int ) id . Second ;
int distance = _currentHistoryID - historyID ;
if ( distance < = 0 )
{
// Shouldn't happen, but this would be a forward jump.
return null ;
}
else if ( distance > _historyUsed )
{
// Gone way back. Empty history, but return null.
_historyUsed = 0 ;
return null ;
}
else
{
int foundIndex = ( _currentHistoryIndex + _historySize - distance ) %
_historySize ;
// Make the found item the top of the stack.
_currentHistoryIndex = ( foundIndex + 1 ) % _historySize ;
_currentHistoryID = historyID + 1 ;
_historyUsed - = distance - 1 ;
return _history [ foundIndex ] ;
}
}
#if TRACE
public void Dump ( out ArrayList arr )
{
arr = new ArrayList ( ) ;
int n = _currentHistoryIndex ;
for ( int i = 0 ; i < _historyUsed ; i + + )
{
n = n - 1 ;
if ( n = = - 1 )
{
n = _history . Length - 1 ;
}
SessionViewStateHistoryItem item = _history [ n ] ;
if ( item ! = null )
{
arr . Add ( String . Format ( CultureInfo . InvariantCulture , "{0}({1})" , item . Url , item . Id ) ) ;
}
else
{
arr . Add ( "(null)" ) ;
}
}
}
#endif
}
}
}