C# – asp.net Invalid character in a Base-64 string

.netasp.netbase64c++viewstate

I have a c# mobile site and have a problem with some of mobile clients. I have posted a trace below but basically browser of phone or wap gateway that phone connects to internet url encodes viewstate hidden input in the form.

/wEPDwULLTExNTMyOTcwOTBkGAEFBlBtTGlzdA9nZA==

becomes

%2FwEPDwULLTExNTMyOTcwOTBkGAEFBlBtTGlzdA9nZA%3D%3D

so viewstate fails.

Is there anyway to override and urldecode viewstate info before proccessing?

System.Web.HttpException: The state information is invalid for this page and might be corrupted. ---> System.Web.UI.ViewStateException: Invalid viewstate. 
 Client IP: 65.91.116.34
 Port: 37172
 User-Agent: SCH-R430 UP.Browser/6.2.3.8 (GUI) MMP/2.0
 ViewState: %2FwEPDwULLTExNTMyOTcwOTBkGAEFBlBtTGlzdA9nZA%3D%3D
 Referer: 
 Path: /mobile/Inbox.aspx ---> System.FormatException: Invalid character in a Base-64 string.
   at System.Convert.FromBase64String(String s)
   at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
   at System.Web.UI.ObjectStateFormatter.System.Web.UI.IStateFormatter.Deserialize(String serializedState)
   at System.Web.UI.Util.DeserializeWithAssert(IStateFormatter formatter, String serializedState)
   at System.Web.UI.HiddenFieldPageStatePersister.Load()
   --- End of inner exception stack trace ---
   --- End of inner exception stack trace ---
   at System.Web.UI.ViewStateException.ThrowError(Exception inner, String persistedState, String errorPageMessage, Boolean macValidationError)
   at System.Web.UI.ViewStateException.ThrowViewStateError(Exception inner, String persistedState)
   at System.Web.UI.HiddenFieldPageStatePersister.Load()
   at System.Web.UI.Page.LoadPageStateFromPersistenceMedium()
   at System.Web.UI.Page.LoadAllState()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest()
   at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
   at System.Web.UI.Page.ProcessRequest(HttpContext context)
   at ASP.mobile_inbox_aspx.ProcessRequest(HttpContext context)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Best Solution

You can implement a custom ViewStatePersister object which handles this. You probably want to derive it from HiddenFieldPageStatePersister. Take a look at this article which shows how to implement compression on top of ViewState, but is very similar to what you need to do.

There's a little bit of hackiness involved: you'll need to use reflection to set a field of the StateFormatter base class which is, contrary to what the MSDN docs say, not marked as virtual so can't be overridden without reflection.