Massimiliano
Top achievements
Rank 1
Massimiliano
asked on 08 Jul 2013, 02:02 PM
It seems that persisting the states on other media and not in the default hiddenfield breaks RadGrid funcionalities (for example paging with "next page" stops at page "2").
The code for changing persistance medium of the viewstate/controlstatef is straightforward and it's derived from Microsoft suggestions on this procedeure.
We also debugged it and both the viewstate and controlstate are correctly saved and restored from both DB or disk.
A simple test on the viewstate was
And about controlstate we readi it on the debugger and this is a screenshot (both in the first page load and after postback same identical controlstate)
http://www.hakkar.it/controlstate-nopostback.jpg
Implementation is in a base page class derived from all pages:
Any hint on why this implementation could break grid functionality while removing it everything works as expected?
Does RadGrid check the "__Viewstate" hidden field directly instead of accessing controlstate/viewstate?
The code for changing persistance medium of the viewstate/controlstatef is straightforward and it's derived from Microsoft suggestions on this procedeure.
We also debugged it and both the viewstate and controlstate are correctly saved and restored from both DB or disk.
A simple test on the viewstate was
If
Not
Page.IsPostBack
Then
ViewState(
"testme"
) =
"test view state"
Else
TestLabel.Text =
"--"
& ViewState(
"testme"
)
End
If
And about controlstate we readi it on the debugger and this is a screenshot (both in the first page load and after postback same identical controlstate)
http://www.hakkar.it/controlstate-nopostback.jpg
Implementation is in a base page class derived from all pages:
Private
pPageStatePersister
As
PageStatePersister
' DB/Disk persisted viewstate
Protected
Overrides
ReadOnly
Property
PageStatePersister
As
PageStatePersister
Get
If
pPageStatePersister
Is
Nothing
Then
If
Not
String
.IsNullOrEmpty(GlobalAppSettings.ViewStatePersister)
Then
pPageStatePersister =
New
ViewStatePersister(
Me
)
Else
pPageStatePersister =
New
HiddenFieldPageStatePersister(
Me
)
End
If
End
If
Return
pPageStatePersister
End
Get
End
Property
Any hint on why this implementation could break grid functionality while removing it everything works as expected?
Does RadGrid check the "__Viewstate" hidden field directly instead of accessing controlstate/viewstate?
11 Answers, 1 is accepted
0
Hello Massimiliano,
Certainly no - the ViewState persisting mechanism is transparent to RadGrid. I suspect the cause for the issue lies somewhere in the persister itself.
Regards,
Tsvetoslav
Telerik
Certainly no - the ViewState persisting mechanism is transparent to RadGrid. I suspect the cause for the issue lies somewhere in the persister itself.
Regards,
Tsvetoslav
Telerik
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to the blog feed now.
0
Massimiliano
Top achievements
Rank 1
answered on 11 Jul 2013, 07:33 PM
Hallo Tsvetoslav and thank you for joining the discussion
Of course this was my first thought as well but couldn't find wehre the persister could be the root of this problem.
As you can see in the code above I made little test to check if viewstate is saved and recovered successfully with
And it works flawslessy. Infact when I push "next page" on my ajaxified RadGrid, the label shows up (I put both the grid and the label in the radajaxmanager update triggered by the grid) with the value "--testme" as it should.
I don't know how to do a similiar check for ControlState if is there any way to (I attached above screenshots on first page load with no postback and after pagination).
The code in the persister is quite simple on it's own:
Implementation for example for the file based solution is this one (and it works correctly with viewstate as I can check wit the label "--testme" above)
The only "odd" think I saw with the debugger is that the Load event of the viewstate is called twice (saved once but called twice) and this shouldn't be the standard behaviour I guess... but I cannot imagine how this could be an issue apart from resource wasting.
Do you have any hint to carry on my debug and track the issue? Some way to peer in the controlstate to check if it's all ok (just in case the screenshot I posted where of no use).
This is very important for me because handling the state off the page allows for a more "liberal" usage of viewstate as a session-like "cache" while keeping page size low of course.
Thanks in advance for any assistance you could provide with this issue.
PS. I'm using this chain of derived classes for my page: BasePage > AdminBasePage > Page + BaseMasterPage > BaseAdminMasterPage > MasterPage. The viewstate persistance implementation resides only in the BasePage.
Of course this was my first thought as well but couldn't find wehre the persister could be the root of this problem.
As you can see in the code above I made little test to check if viewstate is saved and recovered successfully with
If
Not
Page.IsPostBack
Then
ViewState(
"testme"
) =
"test view state"
Else
TestLabel.Text =
"--"
& ViewState(
"testme"
)
End
If
And it works flawslessy. Infact when I push "next page" on my ajaxified RadGrid, the label shows up (I put both the grid and the label in the radajaxmanager update triggered by the grid) with the value "--testme" as it should.
I don't know how to do a similiar check for ControlState if is there any way to (I attached above screenshots on first page load with no postback and after pagination).
The code in the persister is quite simple on it's own:
Namespace
Eva.Settings
Public
Class
ViewStatePersister
Inherits
HiddenFieldPageStatePersister
Private
ReadOnly
connectionString
As
String
Private
ReadOnly
formatter
As
LosFormatter
Public
Sub
New
(page
As
Page)
MyBase
.
New
(page)
connectionString = GlobalAppSettings.ConnectionString
formatter =
New
LosFormatter()
End
Sub
Public
Overrides
Sub
Load()
' Get view state from the hidden field in web page
Dim
viewStateId
As
String
= Page.Request.Form(
"__EVAVS"
)
If
Not
String
.IsNullOrWhiteSpace(viewStateId)
Then
If
GlobalAppSettings.ViewStatePersister =
"SQL"
Then
LoadFromDb(viewStateId)
Else
LoadFromDisk(viewStateId)
End
If
End
If
End
Sub
Public
Overrides
Sub
Save()
If
GlobalAppSettings.ViewStatePersister =
"SQL"
Then
SaveToDb()
Else
SaveToDisk()
End
If
End
Sub
Private
Function
Serialize(viewstatePair
As
Pair)
As
Byte
()
Using mem
As
New
MemoryStream()
formatter.Serialize(mem, viewstatePair)
Return
mem.ToArray()
End
Using
End
Function
Private
Function
Deserialize(buffer
As
Byte
())
As
Pair
Using mem
As
New
MemoryStream(buffer)
Dim
viewstatePair
As
Pair =
DirectCast
(formatter.Deserialize(mem), Pair)
Return
viewstatePair
End
Using
End
Function
Implementation for example for the file based solution is this one (and it works correctly with viewstate as I can check wit the label "--testme" above)
Private
Sub
LoadFromDisk(viewStateId
As
String
)
Dim
viewStatePath
As
String
= Path.Combine(GlobalAppSettings.ViewStateStorePath, viewStateId)
If
Not
File.Exists(viewStatePath)
Then
Throw
New
Exception(
"The Viewstate file "
& viewStateId &
" is missing"
)
Else
Dim
viewStateString
As
String
' Read the viewstate from disk
Try
Dim
sr
As
StreamReader = File.OpenText(viewStatePath)
viewStateString = sr.ReadToEnd()
sr.Close()
Catch
ex
As
Exception
Throw
New
ApplicationException(
"Errore durante il recupero del ViewState dal DB"
, ex)
End
Try
' Deserialize the pair viewstate and controlstat
Dim
viewstatePair
As
Pair = formatter.Deserialize(viewStateString)
ViewState = viewstatePair.First
ControlState = viewstatePair.Second
End
If
End
Sub
Private
Sub
SaveToDisk()
If
ViewState IsNot
Nothing
OrElse
ControlState IsNot
Nothing
Then
Dim
viewstatePair
As
New
Pair(ViewState, ControlState)
Dim
writer
As
New
StringWriter()
Dim
viewStateGuidName
As
String
= System.Guid.NewGuid().ToString()
Dim
viewStatePath
As
String
= Path.Combine(GlobalAppSettings.ViewStateStorePath, viewStateGuidName)
' Serialize the viewstate and controlstate pair into a base64 encoded string
formatter.Serialize(writer, viewstatePair)
' Write the viewstate and controlstate to a text file named after the random GUID
Try
Dim
sw
As
StreamWriter = File.CreateText(viewStatePath)
sw.Write(writer.ToString())
sw.Close()
Catch
ex
As
Exception
Throw
New
ApplicationException(
"Errore durante il salvataggio del ViewState su disco"
, ex)
End
Try
' Add the hidden field to the web page with the viewstate random GUID
Page.ClientScript.RegisterHiddenField(
"__EVAVS"
, viewStateGuidName)
End
If
End
Sub
The only "odd" think I saw with the debugger is that the Load event of the viewstate is called twice (saved once but called twice) and this shouldn't be the standard behaviour I guess... but I cannot imagine how this could be an issue apart from resource wasting.
Do you have any hint to carry on my debug and track the issue? Some way to peer in the controlstate to check if it's all ok (just in case the screenshot I posted where of no use).
This is very important for me because handling the state off the page allows for a more "liberal" usage of viewstate as a session-like "cache" while keeping page size low of course.
Thanks in advance for any assistance you could provide with this issue.
PS. I'm using this chain of derived classes for my page: BasePage > AdminBasePage > Page + BaseMasterPage > BaseAdminMasterPage > MasterPage. The viewstate persistance implementation resides only in the BasePage.
0
Hello Massimiliano,
Please, open up a formal support ticket and attach a runnable copy of your implementation. We shall debug it and get back to you with more information.
Regards,
Tsvetoslav
Telerik
Please, open up a formal support ticket and attach a runnable copy of your implementation. We shall debug it and get back to you with more information.
Regards,
Tsvetoslav
Telerik
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to the blog feed now.
0
Massimiliano
Top achievements
Rank 1
answered on 16 Jul 2013, 03:39 PM
Thank you Tsvetoslav
"Runnable" will not be easy since is a very very complex implementation (is a little cms/framework on its own).
When I have some spare hours I will try to strip it down to a single page with minimum and check that it still doesn't work.
In the meanwhile if you have some suggestions on debugging steps (for example how to chek grid controlstate and what should be there in each pagination or postback) it will be faster.
"Runnable" will not be easy since is a very very complex implementation (is a little cms/framework on its own).
When I have some spare hours I will try to strip it down to a single page with minimum and check that it still doesn't work.
In the meanwhile if you have some suggestions on debugging steps (for example how to chek grid controlstate and what should be there in each pagination or postback) it will be faster.
0
Massimiliano
Top achievements
Rank 1
answered on 16 Jul 2013, 03:43 PM
Hallo Tsvetoslav and thank you for your support. Since its a very complex implementation (I'm developing a little framework/cms on its own) when I'll have a couple of spare hours I will try to strip it down to a "single page" where the issue remains (but I'm afraid that stripping it to single page will remove the issue as well).
In the meanwhile if you have suggestion on debugging, on where to place the breakpoints or debug variables, to check for example what is in the controlstate and what should be there at wich time, I'm sure it will be faster. If not I'll try to prepare the solution you asked when I can.
One consistent issue (but it's just one) is during pagination, pushing the "next" page for example.
In the meanwhile if you have suggestion on debugging, on where to place the breakpoints or debug variables, to check for example what is in the controlstate and what should be there at wich time, I'm sure it will be faster. If not I'll try to prepare the solution you asked when I can.
One consistent issue (but it's just one) is during pagination, pushing the "next" page for example.
0
Hi Massimiliano,
Unfortunately without having a simple runnable example where the problem could be replicated it is very hard to say what the reason for the described issue is. Also the RadGrid ViewState and ControlState are used for many properties (some of them are internal private or protected) and I do not think that we can inspect the states directly. On suggestion here can be to try using PersistenceFramework which is designed for this purpose. More information you can find here:
http://demos.telerik.com/aspnet-ajax/persistence-framework/examples/custom-storage-provider/defaultcs.aspx
http://www.telerik.com/help/aspnet-ajax/persistence-framework-overview.html
Regards,
Radoslav
Telerik
Unfortunately without having a simple runnable example where the problem could be replicated it is very hard to say what the reason for the described issue is. Also the RadGrid ViewState and ControlState are used for many properties (some of them are internal private or protected) and I do not think that we can inspect the states directly. On suggestion here can be to try using PersistenceFramework which is designed for this purpose. More information you can find here:
http://demos.telerik.com/aspnet-ajax/persistence-framework/examples/custom-storage-provider/defaultcs.aspx
http://www.telerik.com/help/aspnet-ajax/persistence-framework-overview.html
Regards,
Radoslav
Telerik
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to the blog feed now.
0
Massimiliano
Top achievements
Rank 1
answered on 19 Jul 2013, 09:41 AM
Thank you Radoslav for your always kind support.
The persistance control is indeed a great addition to the suite but I see it more as a "long term" or "between session" layout/state storage.
My persister instead moves viewstate/controlstate of every page to the db for obvious benefits.
The viewstate is restoring correctly, I've been able to test it (today I will check the NeedDataSource event in the debugger to see if it fires AFTER the other events thus confirming viewstate is ok).
The control state I'm not able to test but, from the persister code I pasted, it should be straightforward. It's serialized together with the viewstate in a pair, so if one works the other should work as well:
I'll try to find the time to render a runnable example. I hope the issue remains even in the simplest scenario, this would speed up thing but now I'm 99% confident the problem is with the controlstate (not the viewstate).
Thanks again
The persistance control is indeed a great addition to the suite but I see it more as a "long term" or "between session" layout/state storage.
My persister instead moves viewstate/controlstate of every page to the db for obvious benefits.
The viewstate is restoring correctly, I've been able to test it (today I will check the NeedDataSource event in the debugger to see if it fires AFTER the other events thus confirming viewstate is ok).
The control state I'm not able to test but, from the persister code I pasted, it should be straightforward. It's serialized together with the viewstate in a pair, so if one works the other should work as well:
Dim
viewstatePair
As
New
Pair(ViewState, ControlState)
I'll try to find the time to render a runnable example. I hope the issue remains even in the simplest scenario, this would speed up thing but now I'm 99% confident the problem is with the controlstate (not the viewstate).
Thanks again
0
Massimiliano
Top achievements
Rank 1
answered on 22 Jul 2013, 08:23 PM
I've been able to strip it down a single page in an auto-contained project and the good news is that the issue persists (so you can help me debug it) and also I've been able to track it down exactly to the origin of the problem, but I don't know why this happens.
The problem is somehow tied to AJAX. Infact if you disable ajax manager the grid works as expected with the disk viewstate persister, if you enable AJAX it seems that controlstate is not persisted across AJAX postabacks.
To check this you can simply click on the "NEXT" page button, or just filter a column, then order a column and you will see the filter is reset, and so on with grouping, etc. Each postback seems resets the controlstate.
I'm opening a ticket as per your suggestion, referring back to this topic. I will update the topic when we found the issue for other users benefit.
Thanks
The problem is somehow tied to AJAX. Infact if you disable ajax manager the grid works as expected with the disk viewstate persister, if you enable AJAX it seems that controlstate is not persisted across AJAX postabacks.
To check this you can simply click on the "NEXT" page button, or just filter a column, then order a column and you will see the filter is reset, and so on with grouping, etc. Each postback seems resets the controlstate.
I'm opening a ticket as per your suggestion, referring back to this topic. I will update the topic when we found the issue for other users benefit.
Thanks
0
Hello Massimiliano,
Could you please try using the StateFormatter when you serialize or deserialize values instead of the LosFormatter:
Also more information about overriding the HiddenFieldPageStatePersister you can find here:
http://stackoverflow.com/questions/1010/how-to-get-the-value-of-built-encoded-viewstate
http://aspguy.wordpress.com/tag/hiddenfieldpagestatepersister/
http://dotnetinside.com/framework/v2.0.50727/framework/v2.0.50727/System.Web/HiddenFieldPageStatePersister
Also please note that this is a custom implementation and it is out of our support scope.
I hope this helps.
Regards,
Radoslav
Telerik
Could you please try using the StateFormatter when you serialize or deserialize values instead of the LosFormatter:
Private
Sub
LoadFromDisk(viewStateId
As
String
)
Dim
viewStatePath
As
String
= Path.Combine(AppDomain.CurrentDomain.GetData(
"DataDirectory"
).ToString(), viewStateId)
If
Not
File.Exists(viewStatePath)
Then
Throw
New
Exception(
"The Viewstate file "
& viewStateId &
" is missing"
)
Else
Dim
viewStateString
As
String
' Read the viewstate from disk
Try
Dim
sr
As
StreamReader = File.OpenText(viewStatePath)
viewStateString = sr.ReadToEnd()
sr.Close()
Catch
ex
As
Exception
Throw
New
ApplicationException(
"Errore durante il recupero del ViewState dal DB"
, ex)
End
Try
Dim
viewstatePair
As
Pair = StateFormatter.Deserialize(viewStateString)
ViewState = viewstatePair.First
ControlState = viewstatePair.Second
End
If
End
Sub
Private
Sub
SaveToDisk()
If
ViewState IsNot
Nothing
OrElse
ControlState IsNot
Nothing
Then
Dim
viewstatePair
As
New
Pair(ViewState, ControlState)
Dim
writer
As
New
StringWriter()
Dim
viewStateGuidName
As
String
= System.Guid.NewGuid().ToString()
Dim
viewStatePath
As
String
= Path.Combine(AppDomain.CurrentDomain.GetData(
"DataDirectory"
).ToString(), viewStateGuidName)
Dim
ser
As
String
= StateFormatter.Serialize(
New
Pair(ViewState, ControlState))
' Write the viewstate and controlstate to a text file named after the random GUID
Try
Dim
sw
As
StreamWriter = File.CreateText(viewStatePath)
sw.Write(ser)
sw.Close()
Catch
ex
As
Exception
Throw
New
ApplicationException(
"Errore durante il salvataggio del ViewState su disco"
, ex)
End
Try
' Add the hidden field to the web page with the viewstate random GUID
Page.ClientScript.RegisterHiddenField(
"__EVAVS"
, viewStateGuidName)
End
If
End
Sub
Also more information about overriding the HiddenFieldPageStatePersister you can find here:
http://stackoverflow.com/questions/1010/how-to-get-the-value-of-built-encoded-viewstate
http://aspguy.wordpress.com/tag/hiddenfieldpagestatepersister/
http://dotnetinside.com/framework/v2.0.50727/framework/v2.0.50727/System.Web/HiddenFieldPageStatePersister
Also please note that this is a custom implementation and it is out of our support scope.
I hope this helps.
Regards,
Radoslav
Telerik
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to the blog feed now.
0
Massimiliano
Top achievements
Rank 1
answered on 24 Jul 2013, 07:48 PM
I appreciate very much your help. I understand this is out of scope of Telerik support, but I really have to find a way to solve it if I want to have a RadGrid at his full potential ;)
Will be back tomorrow with the testing results. Don't understand why Ajax should interfere with LOS formatter but will read the link you proposed in depth. Thanks again
Will be back tomorrow with the testing results. Don't understand why Ajax should interfere with LOS formatter but will read the link you proposed in depth. Thanks again
0
Massimiliano
Top achievements
Rank 1
answered on 25 Jul 2013, 04:32 PM
Here I am. I tried your solution and sadly it didn't work. The problem was not tied to the serializer but somehow to using or not using AJAX.
Infact without AJAX everything works, when I enable RadAjaxManager it doesn't work anymore.
So I focused my search on custom viewstate persister + ajax related issues and luckly come out with a post that provided a working solution.
I think it's right to link the original source to which I feel particularly thankful this time (if this violates Telerik forum rules somehow please remove the whole line/link without problems): http://www.munsplace.com/blog/2007/10/29/custom-pagestatepersister-and-ajax/comment-page-1/
I guess this will be much useful for anyone implementing a similar solution.
Simply put, instead of registering the hidden field with
It should be registered with
That way the script manager is "aware" of the field and keeps it in sync between Ajax requests.
Tested and working.
Infact without AJAX everything works, when I enable RadAjaxManager it doesn't work anymore.
So I focused my search on custom viewstate persister + ajax related issues and luckly come out with a post that provided a working solution.
I think it's right to link the original source to which I feel particularly thankful this time (if this violates Telerik forum rules somehow please remove the whole line/link without problems): http://www.munsplace.com/blog/2007/10/29/custom-pagestatepersister-and-ajax/comment-page-1/
I guess this will be much useful for anyone implementing a similar solution.
Simply put, instead of registering the hidden field with
Page.ClientScript.RegisterHiddenField("__EVAVS", viewStateGuidName)
It should be registered with
ScriptManager.RegisterHiddenField(Page, "__EVAVS", viewStateGuidName)
That way the script manager is "aware" of the field and keeps it in sync between Ajax requests.
Tested and working.