Serialization issue when using StateServer mode in asp.net - asp.net

If my session mode is set to "StateServer", I get a serialization error because I'm storing a list of controls in a session, and adding those into a aspx placeholder control. Here's the code that I think is problematic:
Protected Sub AddCtrl(ByVal ctrl As Control)
Dim l As List(Of Control)
If Session("Ctrls") Is Nothing Then
l = New List(Of Control)
Else
l = DirectCast(Session("Ctrls", List(Of Control))
End If
End Sub
Later on in the code, I iterate through the Ctrls session object, and add each control to a placeholder in the HTML.
What can do I to fix this problem? I tried to create a custom list that inherits from list, and made it serializable and use the custom list instead, but that didn't do it:
<Serializable()> _
Public Class MyList
Inherits List(Of Control)
I tried using ViewState instead and that also didn't do it. Seeking advice...
Thanks!

Related

EnableViewState causing loss of value

Using vb.net 4.5 and Telerik 2017.2.711.45 (Q2)
I am trying to get radgrid filter expressions and a public string variable to persist across postbacks.
With EnableViewState=FALSE, radgrid filter expressions do not persist through postback, however a public string variable (stringVar) does persist.
When I set EnableViewState=TRUE the filter expressions in radgrid do persist, however it causes stringVar to not persist.
From my understanding of ViewState, it makes no sense that setting EnableViewState=TRUE would cause stringVar to not persist across postbacks. I would love to know why this is occurring and what I could do to resolve this.
EDIT:
The highlighted Line is where an error would be thrown because ReportTitle no longer has a value.
Partial Class displayxslgrid
Public ReportTitle As String
Public ReportsDB As reportDataBase
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Page.EnableViewState = True
Reports = New reportDataBase.Global_Functions(System.Web.HttpContext.Current)
End Sub
Protected Sub RadGrid1_NeedDataSource(sender As Object, e As Telerik.Web.UI.GridNeedDataSourceEventArgs) Handles RadGrid1.NeedDataSource
Call BindRadGrid1()
End Sub
Protected Sub RadGrid1_ItemCommand(ByVal source As Object, ByVal e As Telerik.Web.UI.GridCommandEventArgs) Handles RadGrid1.ItemCommand
Dim strReportTitle As String
Select Case e.CommandName
Case RadGrid.ExportToExcelCommandName, RadGrid.ExportToWordCommandName, RadGrid.ExportToCsvCommandName
strReportTitle = ReportTitle.Trim
End Select
End Sub
Public Sub BindRadGrid1()
Dim strReportTitle As String
Dim dt As DataTable = Nothing
ReportTitle = dt.Rows(0).Item("ReportTitle")
strReportTitle = dt.Rows(0).Item("ReportTitle").ToString
'RadGrid1 Data source gets set here along with other stuff
End Sub
End Class
Using view state is normal, and Telerik controls need it to preserve their values across post-backs. A public string property on your page class should not persist, and should be set/calculated every time. If you absolutely need something like that to persist, save the value in a hidden server control, or have it in the QueryString of the URL.
So it turns out, that that variable was not truly persisting. It was getting its value from the bindradgrid1. When EnableViewState=True the need data source event is not fired, therefore the bindradgrid1 is not called and the variable does not get a value. Simple fix was adding a bindradgrid1() in the item command sub so that even with EnableViewState=True, bindradgrid1() will still get called. Thanks for all who helped.

Anyway to modify a masterpage control from a contentpage update panel?

Here is what I came up with for a single-source popup modal for a web application.
I put a placeholder on the master page and the code below in a separate class. The class file receives the message and builds the modal html.
This works on full postback, but not when called from within an ajax update panel.
I know why. I just don’t know of any way around it. Any ideas?
Public Class Common
Inherits SiteMaster
Public Shared Sub showModalMsg(ByVal sMsg As String)
Dim lbl As New Label
lbl.Text = sMsg
'(for simplicity, the building of the div to make the modal is omitted)
Dim pageHandler = HttpContext.Current.CurrentHandler
If TypeOf pageHandler Is System.Web.UI.Page Then
Dim ph As PlaceHolder = DirectCast(pageHandler, System.Web.UI.Page).Master.FindControl("phModalDialog")
If ph IsNot Nothing Then
ph.Controls.Add(lbl)
End If
End If
End Class
Ok, here is what I did. I added an optional variable called 'container' that can be passed when calling the dialog within an update panel.
Public Shared Sub showModalMsg(ByVal sMsg As String,
Optional ByVal container As Control = Nothing)
I posted my full solution here:
How can I use a single modal across my web application and avoid repetative html on every page?

Multiple ascx (user controls) that use the same server side code

I currently have multiple user controls in a default page. Each one has a different grid that is going to become a dashboard. However to cut down on repeating code, some of the controls use the same datasource. Is there anyway to have them all share the same datasource. Or if necessary all use the same OnSelecting statement that I could define elsewhere?
Such as one of the LinqDataSources selects all the users in a group, this displays them all in a gridview. However a detailed gridview below that in a separate ascx control uses the same data, but displays it in another way, grouping differently etc. However they both (if placed on one page) use the same datasource. If there anyway for them to use the same selecting Sub somehow? Maybe part of a class somewhere else in the code?
Ok after further research into alternate ways I've decided to place my select on the default page:
Public Function returnGroup() As List(Of Group)
'Use standard LINQ to SQL function to get list of what is needed
End Function
This has been used in combination with the Structure:
Structure Group
Public Property Title As String : Public Property GroupID As Integer
Public Property GroupCode As String
End Structure
So when combined it creates:
Public Function returnGroup() As List(Of Group)
'Use standard LINQ to SQL function to get list of what is needed
Return LINQToSQL_Select.Select(Function(chX) New Group With {.Title = chX.Title} '... etc
End Function
This is then called in the ascx page:
Protected Sub Page_Load(ByVAl sender as object, ByVal e as eventargs) Handles Me.Load
Dim cDef as New _Default
gvGroup.DataSource = cDef.returnGroup() : gvGroup.DataBind()
End Sub

ASP.NET BasePage Class Page_Load not Fired on Postback

I have the following BasePage class...
Public Class BasePage
Inherits System.Web.UI.Page
Private litError As Literal
Protected SO As Session
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
SO = Session.Item("SO")
If SO Is Nothing Then
Session.Abandon()
Response.Redirect("~/timeout.htm")
End If
litError = Page.FindControl("litError")
If litError IsNot Nothing Then
litError.Visible = False
End If
End Sub
Protected Sub ShowMessage(ByVal Message As String)
Show(Message, "message")
End Sub
Protected Sub ShowError(ByVal Message As String)
Show(Message, "error message")
End Sub
Protected Sub ShowSuccess(ByVal Message As String)
Show(Message, "success message")
End Sub
Private Sub Show(ByVal Message As String, ByVal CssClass As String)
If litError IsNot Nothing Then
litError.Text = String.Format("<span class=""{0}"">{1}</span>", CssClass, HttpUtility.HtmlEncode(Message))
litError.Visible = True
End If
End Sub
End Class
Every page in this application inherits this class. The SO variable represents a custom session class, that is very simple and just holds a couple of basic settings to be used throughout the application. The problem is, my Page_Load in this base class does not fire if a natural postback occurs (in this case, it is a gridview postback by sorting/paging). Then later in my code when I reference SO, I get a null reference exception because it hasn't been pulled from session.
Why doesn't the base Page_Load fire?
Try moving your code into the Page_Init event.
Microsoft has some info on each event in the lifecycle http://msdn.microsoft.com/en-us/library/ms178472.aspx. This MSDN page tells you what types of things you should handle in each event.
You might want to think about implementing SO as a property, where the Get does (not sure if this is correct VB...)
Dim so As Session = Session.Item("SO")
If so Is Nothing Then
Session.Abandon()
Response.Redirect("~/timeout.htm")
End If
return so
It could be that something else is happening in the Init events that is causing it to fail. So rather than it not being called it just hasn't been called yet.
It could be that the autoevent wireup isn't wiring it up correctly, tend to override the OnInit event and attach the events manually myself, I have also read somewhere that this improves perfomance by not requiring the framework to do heaps of reflection on every post.
But back to your problem... try making the SO object private and create a property accessor for it that first checks that if the private is set, if not set it, before returning the private variable. If it isn't set and can't be found then it can abort the same way you are doing in the Load. This means that to load the variable you won't be dependent on the Page_Load from firing and thus the SO object should be available for you during the init routines, if you need it.

Dynamic nested master pages, shared properties

I have a base master page that specifies the main layout template of a website. It also handles some logic that changes tabs depending on the section, and also sets page meta information.
I'm dynamically loading nested master pages by looking at the querystring, loading up a record from the database, and setting the nested master page dynamically based on a value found in that record. I need to load dynamic nested master pages for layout and functional differences.
There is additional information in that record that I want to use in the base master page and in the dynamically loaded master page so I can avoid additional database calls.
Currently, I have set up a class that inherits MasterPage to act as the base class for the base master page. I have a shared (static) property that holds the object representing the database call that I want to share between the base master page and the nested, dynamically called master page.
It works, but it seems a little ugly. Are there any other better solutions?
You could always pass the record in the HttpContext.Items collection. Once it is in the Items collection it is available to every thing that can reach the HttpContext for the duration of the request.
Ok, I had to sleep on this one a bit, but I came up with a cleaner solution. I ended up using a base class for the page, instead of a base class for the master page. The base page sets the meta that I was going to set in the base master page.
Public Class PageBase
Inherits Page
Private _DocDetails As FolderDocument
Public Overridable ReadOnly Property DocDetails() As FolderDocument
Get
Return _DocDetails
End Get
End Property
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack() Then
SetMeta()
End If
End Sub
Protected Sub SetMeta()
If DocDetails IsNot Nothing Then
Page.Title = DocDetails.MetaTitle
If DocDetails.MetaKeywords <> String.Empty Then
Dim metaKeywords As New HtmlMeta()
metaKeywords.Name = "Keywords"
metaKeywords.Content = DocDetails.MetaKeywords
Page.Header.Controls.Add(metaKeywords)
End If
If DocDetails.MetaDescription <> String.Empty Then
Dim metaDescription As New HtmlMeta()
metaDescription.Name = "Description"
metaDescription.Content = DocDetails.MetaDescription
Page.Header.Controls.Add(metaDescription)
End If
End If
End Sub
End Class
..And then the aspx page inherits this base page and dynamically sets the master page.
<%# Page Language="VB" Inherits="PageBase" %>
<script runat="server">
Private _DocDetails As FolderDocument
Public Overrides ReadOnly Property DocDetails() As FolderDocument
Get
Return _DocDetails
End Get
End Property
Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs)
_DocDetails = FolderDocuments.GetFolderDocument()
If _DocDetails IsNot Nothing Then
If _DocDetails.MasterPage <> "" Then
Me.MasterPageFile = String.Format("~/templates/{0}.master", _DocDetails.MasterPage)
End If
End If
End Sub
</script>
...and in the dynamically called master page I can reference the page's base class by casting:
Dim parentPage As PageBase = DirectCast(Page, PageBase)
Response.write(parentPage.DocDetails.Title)

Resources