how to access webpage control in a class - asp.net

I took a div id="DivErr" runat="server"
This is my Web Page written a class within
Public Class ReceiptInv Inherits System.Web.UI.Page
Partial Class MyTimer
Private Sub New()
End Sub
Public Shared timer As New Timer(5000)
' Enable the timer to run
Public Shared Sub StartRuning()
AddHandler timer.Elapsed, AddressOf timer_Elapsed
timer.Start()
End Sub
' This method will be called every 5 seconds
Private Shared Sub timer_Elapsed(ByVal sender As Object, ByVal e As ElapsedEventArgs)
Dim TMR As New ReceiptInv
TMR.DivErr.Visible = False
End Sub
End Class
End Class
I want to make this DivErr visible false in every 5 seconds.
But error in line
TMR.DivErr.Visible = False
NullReferenceException Unhandled By Usercode
Object reference not set to an instance of an Object
Can anyone tell what i am doing wrong ?? Thanks in Advance..

You need to get a real instance of the page, then you can access the controls and properties of it. Since your method is Shared you cannot access controls of the current page's instance (easily).
But you can try to get the page-instance via HttpContext.CurrentHandler.
Private Shared Sub timer_Elapsed(ByVal sender As Object, ByVal e As ElapsedEventArgs)
Dim page = TryCast(HttpContext.CurrentHandler, ReceiptInv)
If page IsNot Nothing Then
page.DivErr.Visible = False
End If
End Sub
However, why does the method need to be shared at all? A Shared timer is shared by all requests!
Apart from that i suspect that you're trying to make a control visible/invisible every 5th second. That won't work this way since you're using a server timer. You could use an ASP.NET-Ajax-Timer instead: http://msdn.microsoft.com/en-us/library/bb386404(v=vs.100).aspx

Related

How to persist an object in webform

As I'm self taught my VB coding is not bad but my use of OOP is poor. I'm sure this can be done but I have not found out how yet.
I am building a webforms app which needs to grab data about a user from AD. I have a Person Class which I can use as follows
Public Class _Default
Inherits System.Web.UI.Page
Dim LoggedOnPerson As Person 'Added here so available throughout class
Private strLoggedOnUser As String
Private strADDomain As String
Private strADUserID As String
Public Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
strLoggedOnUser = Request.ServerVariables("LOGON_USER").ToUpper
strADDomain = strLoggedOnUser.Split("\")(0)
strADUserID = strLoggedOnUser.Split("\")(1)
If Not IsPostBack Then
'Dim LoggedOnPerson As Person *** changed to
LoggedOnPerson = New Person
'Get details from AD for logged on user
LoggedOnPerson.GetDetails(strADDomain, strADUserID)
'Store in Session
Session("LoggedOnUser") = LoggedOnUser
'This will now give me access to details such as
'LoggedOnPerson.EmailAddress
'LoggedOnPerson.GivenName
'LoggedOnPerson.TelephoneNo etc.
Else
'Postback so pull in details from Session
LoggedOnUser = Session("LoggedOnUser")
End If
End Sub
End Class
My problem is that I cannot access LoggedOnPerson in other events. e.g.
Public Sub SaveDetails()
Dim email As String = LoggedOnPerson.Email
'This now produces correct result. No error that LoggedOnPerson is not declared
End Sub
I of course get LoggedOnPerson is not declared error. How can I get around this.
You have created the object of "Person" inside Page_Load event. Take it outside and declare at the class level. Also add that object to view state/session state on Page_Load event and typecast it to "Person" class inside other events.

using control states in server control

I have a server control that I am trying to get to save properties as control states but for some reason the properties are not persisting across partial postbacks.
The psuedo code is as follows:
Public Class FileUpload
Inherits ScriptControl
Implements INamingContainer, IPostBackEventHandler
Public Property newFileExt() As String
Get
Dim foundList As String = DirectCast(ViewState(Me.UniqueID & "_fileExt"), String)
If foundList IsNot Nothing Then
Return foundList
Else
Return String.Empty
End If
End Get
Set(ByVal value As String)
ViewState(Me.UniqueID & "_fileExt") = value
End Set
End Property
Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
MyBase.OnInit(e)
Page.RegisterRequiresControlState(Me)
End Sub
Protected Overrides Function SaveControlState() As Object
Dim controlState(6) As Object
controlState(0) = MyBase.SaveControlState()
controlState(1) = newFileExt
Return controlState
End Function
Protected Overrides Sub LoadControlState(ByVal savedState As Object)
Dim controlState() As Object
controlState = CType(savedState, Object)
MyBase.LoadControlState(controlState(0))
newFileExt = CType(controlState(1), String)
End Sub
end class
On this control is an asyncFileUpload ajaxcontroltoolkit control and a button. I have an event for upload complete:
Protected Sub SaveUploadedFile(ByVal sender As Object, ByVal e As AjaxControlToolkit.AsyncFileUploadEventArgs) Handles asyncFileUpload.UploadedComplete
newFileExt= "Some Value"
end sub
Protected Sub bntSelectResults_click(ByVal sender As Object, ByVal e As EventArgs) Handles bntSelectResults.Click
If (newFileExt= "") Then
'this always returns as empty
End If
end sub
So, UploadedComplete is complete it should set the controls state. then, when the user click the button it should read it. Through debugging, I can see that it is set correctly in UploadedComplete event but null when read. Is this due to the cycle of the page or something?
Thanks
jason
EDIT
I traced out the path for how the page cycle is running:
User clicks the async file upload control's browse button and selects a file. This causes the upload process to start
a. OnInit gets called
b. LoadControlState gets called
c. OnLoad gets called
d. asyncFileUpload.UploadedComplete gets called and I set the newFileExt property
here.
e. SaveControlState gets called. newFileExt is set here properly
User clicks a button on the control that initiates another partial postback/update of the update panel
a. OnInit gets called
b. LoadControlState gets called. I can see that the newFileExt property is not set
c. OnLoad gets called
d. Buttons click event gets called and the property is read (which is no longer set)
e. SaveControlState gets called and cycle ends
So, as best as I can tell, the asyncFileUpload application has issues with ViewStates/ControlStates. I ended up just just using sessions.

Lost HttpContext in a custom event

I'm getting the 'Response is not available in this context error' calling the following function:
Private Sub ReloadPage(ByVal inNumber As Integer) Handles tempaux.Advertise
'Response.Redirect("tope.aspx?dep=" & CStr(inNumber))
Response.Write("<script>window.open('tope.aspx?dep= & CStr(inNumber)','topFrame');</script>")
End Sub
I've changed the line adding the System.Web.HttpContext.Current before Response.Write and I get 'Object reference not set to an instance of an object'.
To give some background: tope.aspx is, as you can see, opened in topframe. As soon as it loads it starts a CustomTimer object I've defined:
Public Class tope
Inherits System.Web.UI.Page
Public funciones As funciones = New funciones
Dim WithEvents tempaux As CustomTimer = Global.objCustomTimer
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim inUserProfile As Int64
Try
tempaux.StartTimer()
Catch ex As Exception
'bla bla
End Try
As you can see I've declared the CustomTimer in the Global.asax. The CustomTimer object raises an Advertise event every 5 seconds and passes 'inNumber' as a parameter for the tope.aspx page to refresh some label, a simple thing. CustomTimer is a class I made to manage the timer, it doesn't inherits any other class( For what I've learned in my search it has to inherit some httpthing but I'm not sure). I'm guessing that at some point the httpcontext is being lost (I've searched in google and I couldn't figure its lifecycle or whatever information that tells me why it 'dies). Can anyone help me to find out what is the problem?
thanks
Your timer exists outside of the tope page class, so it is possible that the timer event is firing after the response from the page is complete and there is no longer a HttpContext.Current instance.
It sounds like what you are trying to do is to change an advertising banner on a page every 5 seconds, once the page is loaded. You need to do that using a javascript timer, which would fire every 5 seconds and make a request back to your web server for a new advertisement.

Find out what stage of the life cycle a control is up to in ASP.NET WebForms

From the outside of a control, is it possible to find out what stage of the Page LifeCycle (Init, Load, PreRender etc), a particular control or page is up to?
For example, in pseudo code:
if myControl.CurrentLifeCycle == Lifecycle.Init
{ do something }
I'm afraid there is no builtin function to check in what Page-Lifecycle phase a Page is.
It is also difficult to add this functionality without handling all events in the Page itself, because some events are protected. Therefore you could also inherit the LifeCycleListener-class from Control, add it in the constructor to the page listening and override all events.
If you only need the public "phases" PreInit,Init,Load,DataBinding,PreRender,Unload,Disposed have a look at following approach(VB.Net, but i think you'll get the idea):
Public Enum LifeCyclePhase
AfterPreInit
AfterInit
AfterLoad
AfterDataBinding
AfterPreRender
AfterUnload
AfterDisposed
End Enum
Public Interface ITrackingLifeCycle
ReadOnly Property GetLifeCycleListener() As LifeCycleListener
End Interface
Public Class LifeCycleListener
Public Sub New(ByVal ctrl As Control)
Me._PageListening = ctrl.Page
AddListener()
End Sub
Private _CurrentPhase As LifeCyclePhase
Private _PageListening As Page
Public ReadOnly Property CurrentPhase() As LifeCyclePhase
Get
Return _CurrentPhase
End Get
End Property
Public ReadOnly Property PageListening() As Page
Get
Return _PageListening
End Get
End Property
Private Sub AddListener()
AddHandler _PageListening.PreInit, AddressOf PreInit
AddHandler _PageListening.Init, AddressOf Init
AddHandler _PageListening.Load, AddressOf Load
AddHandler _PageListening.DataBinding, AddressOf DataBinding
AddHandler _PageListening.PreRender, AddressOf PreRender
AddHandler _PageListening.Unload, AddressOf Unload
AddHandler _PageListening.Disposed, AddressOf Disposed
End Sub
Private Sub PreInit(ByVal sender As Object, ByVal e As EventArgs)
Me._CurrentPhase = LifeCyclePhase.AfterPreInit
End Sub
Private Sub Init(ByVal sender As Object, ByVal e As EventArgs)
Me._CurrentPhase = LifeCyclePhase.AfterInit
End Sub
Private Sub Load(ByVal sender As Object, ByVal e As EventArgs)
Me._CurrentPhase = LifeCyclePhase.AfterLoad
End Sub
Private Sub DataBinding(ByVal sender As Object, ByVal e As EventArgs)
Me._CurrentPhase = LifeCyclePhase.AfterDataBinding
End Sub
Private Sub PreRender(ByVal sender As Object, ByVal e As EventArgs)
Me._CurrentPhase = LifeCyclePhase.AfterPreRender
End Sub
Private Sub Unload(ByVal sender As Object, ByVal e As EventArgs)
Me._CurrentPhase = LifeCyclePhase.AfterUnload
End Sub
Private Sub Disposed(ByVal sender As Object, ByVal e As EventArgs)
Me._CurrentPhase = LifeCyclePhase.AfterDisposed
End Sub
End Class
The handler in this class are called after the handler in the page itself, so if you f.e. check the CurrentPhase in Page.Init you'll get PreInit. Therefor i have called this phase AfterPreInit.
Partial Public Class _Default
Inherits System.Web.UI.Page
Implements ITrackingLifeCycle
Private lcl As New LifeCycleListener(Me)
Public ReadOnly Property GetLifeCycleListener() As LifeCycleListener Implements ITrackingLifeCycle.GetLifeCycleListener
Get
Return lcl
End Get
End Property
You can now check the lifecycle-phase everywhere, even without a reference to a control via HttpContext.Current:
Public Class FooClass
Public Shared Sub Foo()
If Not (HttpContext.Current Is Nothing OrElse HttpContext.Current.Handler Is Nothing) Then
If TypeOf HttpContext.Current.CurrentHandler Is ITrackingLifeCycle Then
Dim page As ITrackingLifeCycle = DirectCast(HttpContext.Current.CurrentHandler, ITrackingLifeCycle)
Dim phase As LifeCyclePhase = page.GetLifeCycleListener.CurrentPhase
End If
End If
End Sub
End Class
This is neither tested sufficiently nor used by myself and certainly improvable, but maybe it helps you in your current situation.
I think what you try to achieve is conceptually wrong because you are thinking at the page events as page state. The page can’t be at “OnInit/OnLoad/…” state just because it’s an event.
What do you need it for? maybe we could suggest you a better approach to achieve your goal.
The „outside of your control” is the „inside” of another control or page or something being in a linked state of the lifecycle. You know its state already without testing.
I found out there is actually an internal property of the Page class that does just what I am looking for: it is an enum called ControlState:
internal enum ControlState
{
Constructed,
FrameworkInitialized,
ChildrenInitialized,
Initialized,
ViewStateLoaded,
Loaded,
PreRendered
}
I believe it is possible to access internal members in C#4, see here
As far as I understand the page lifecycle, you can't do it. Basically, Page class is the guy that has to raise events in a specific order. There is nothing in built that will tell the stage of processing. But in order to something, you can create a property and set up this property in different stages of processing.

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.

Resources