How can I share a variable from sub routine to sub routine? - asp.net

I have a sub routine where I pull in information from a database. I want to use variables from this sub routine in another sub routine. I tried making everything public but it doesn't want to be friendly and share.
Dim strEmail as String
Public Sub readDB()
strEmail = "whatever#doohikcy.com"
End Sub
Public Sub submit_btn(ByVal sender As Object, ByVal e As EventArgs)
Response.Write(strEmail)
End Sub
The readDB would read the database and set the variables and do whatever it needs to do. Then when they submit the form it would e-mail the form to whatever the email address was.

Every time an asp.net page loads, the global variables are wiped out. You can avoid this by using Session variables.
Public Sub readDB()
Session("strEmail") = "whatever#doohikcy.com"
End Sub
Then:
Public Sub submit_btn(ByVal sender As Object, ByVal e As EventArgs)
Response.Write(CStr(Session("strEmail")))
End Sub

Passing them as arguments is great, if the sequence of calls to the subs in question makes that feasible. If you literally need a variable that is visible to different subs in the same class (code-behind page in ASP.Net), what you are looking for is probably a private member variable. Declare it outside of any sub or function with the access modifier Private, and all the subs in the class will be able to access it.
Private _foo As String
The underscore is a convention that some people love, some hate. It comes in handy in VB if you want to define a property to expose the variable, where you can't use Foo as distinctly different from foo, but that's another story.
This is not the same as what would generally be understood by the term Global variable in the ASP.Net sense, where the variable would be visible throughout the application context, which lends itself to unintended consequences in the least. A private member variable is only visible to the class that owns it.
EDIT: Your example code was added after my initial answer. My VB is a little rusty but as you've written it, strEmail looks like it should have class-level visibility, including inside of submitbtn (someone correct me if I'm wrong). One possibility, since you mentioned that you are calling readDB in Page_Load is if you're checking for postback in page load, and only calling readDB on the initial load, not on postback, which would be the case when the button is clicked. You may have seen examples that include a check for Postback out of hand and not realized what it does (I only suggest that because you mentioned that you are new to ASP.Net and it's not intuitive if you're new to it--no offense intended).
Protected Sub Page_Load (sender as object, e as EventArgs)
If Not IsPostback
// this doesn't get called when the button is clicked so
// strEmail would not be populated when submitbtn is invoked
readDB
End If
End Sub
That's a bit of a guess out of nowhere though, so it might be way off base. Have you set break-points in Page_Load, readDB and submitbtn to see the state of strEmail in each?

Related

Dim WithEvents Topic

Well,I am beginner in Vb.NET although I had started learning few years back then took break again started and again break. So,anyways I am still the beginner and I am unable to understand what this WithEvents actually does and how and when to be used?I was studying on Dim and came across Dim WithEvents. I tried finding articles but all of them got bit higher level programming code compared to my level so it's gonna take time for me to reach that level.Until then for now I want to know WithEvents actual usage. Can someone give me any simple program that can be the clarity of WithEvents?
Source Links :
Generic WithEvents
VB.NET: WithEvents not Working
Strange WithEvents thing
WithEvents+Handles+Overrides
in vb.net how do I declare a public variable from a private sub
https://msdn.microsoft.com/en-us/library/stf7ebaz(v=vs.90).aspx
Thank you.
In short, WithEvents tells VB that the object you are declaring can raise events and that you intend to handle those events. This keyword goes hand in hand with the Handles keyword.
Create a new form and then add a button to it. Then double-click the button. VB will generate code similar to the following (notice the Handles keyword):
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
End Sub
What you don't immediately see is the declaration for the button. If you look into the Form1.Designer.vb file you will see a line like this:
Friend WithEvents Button1 As System.Windows.Forms.Button
Notice the WithEvents. Since the button will raise events, the variable must be declared using that keyword.

Trying to get Session value in Global.asax, but it is NULL

I have a session which contains a List(of String) which I create on Main.aspx. In my Global.asax I execute the following code to retrieve the Session value after a Timer is fired.
Private Sub Application_AcquireRequestState(sender As Object, e As EventArgs)
If System.Web.HttpContext.Current.Session IsNot Nothing Then
If Session("Products") IsNot Nothing Then
Response.Write(Session("Products").ToString())
End If
End If
End Sub
However, Session("Products") returns Null and the Sub is exited. I wonder if End Sub in Main.aspx releases the Session and therefore whenever the Timer fires, the Session is empty. Any thoughts?
In your Main.vb code behind, be sure to inherit the System.Web.SessionState.IRequiresSessionState interface in addition to whatever is being inherited.
Something like this should work:
Public Class Main
Inherits System.Web.UI.Page, System.Web.SessionState.IRequireSessionState
' Your application code
End Class
This is strange behavior though as ASP.NET webpages should already handle session data. Usually, you inherit IRequireSessionState on generic handlers (.ashx) since they don't support session data by default.

Storing and restoring properties in ASP.NET derived control

I have created an ASP.NET class derived from the standard WebControls.TextBox, with the intention of adding extra properties that will persist between post-backs. However, I cannot figure how to get the values in these properties to persist.
I have tried setting the value of the properties into the controls ViewState as part of the PreRender handler, but the value is then not accessible in the Init handler on the post-back, because the ViewState has not yet been setup.
I could look for the ViewState value in the Load handler of the control, but if the page/usercontrol that is using the control asks for the properties value during its Load handler, the control hasn't yet reached it's Load handler, and it therefore not there.
My current class looks something like this...
Public Class MyTextBox
Inherits TextBox
Private _myParam As String = ""
Public Property MyParam As String
Get
Return _myParam
End Get
Set(value As String)
_myParam = value
End Set
End Property
Private Sub MyTextBox_Init(sender As Object, e As EventArgs) Handles Me.Init
If Page.IsPostBack Then
_myParam = ViewState("myParam")
End If
End Sub
Private Sub MyTextBox_PreRender(sender As Object, e As EventArgs) Handles Me.PreRender
ViewState("myParam") = _myParam
End Sub
End Class
I must be missing something really simple, such as whether there is an attribute I can set against the property.
UPDATE
Thanks to #AVD pointing out that I really had very little clue about the ViewState and the Init / Load stages, I finally figured it all out.
If you have the time (and if you're doing any major ASP.NET work, you need to make the time) please read the Understand ASP.NET View State document that #AVD pointed me to. It will explain a lot.
However, what it didn't explain is if you place your control within a <asp:Repeater>, you may as well throw all the rules out of the window... and that is exactly the problem I was experiencing.
In the end, the way I managed to get it to work was to use a <asp:PlaceHolder> control within the repeater, create an instance of my control within the ItemDataBound handler of the repeater, and then add the control to the <asp:PlaceHolder>... all done within the Init section (which fortunately I'm able to do).
As Andrew found out in this previous question you can end up in a chicken/egg situation, where you need to create the controls in the Init, but you won't know what controls you need until the Load.
(I have still made AVD's answer the correct one, because in the context of my original question, it is absolutely correct).
You have to store/retrieve value to/from ViewState within the properties accessors.
Public Property MyParam As String
Get
If IsNothing(ViewState("myParam")) Then
return string.Empty
End IF
Return ViewState("myParam").ToString()
End Get
Set(value As String)
ViewState("myParam") = value
End Set
End Property

How to register data for validation using RegisterForEventValidation in asp.net

I would like to know the method of using RegisterForEventValidation in asp.net
My problem is this.
If I enable eventvalidation, then changing the controls using javascript and then posting the information back to the server later on throws up an error.
But If I disable event validation, the data present/selected in the controls is not available in the event handlers in code behind.
So, how should one resolve such issues?
Also, are there are any good articles that explain the issue and a resolution in detail? Tried googling. Came across many articles. But nothing that matched my expectations.
A small progress.
If I do the below, the event validation error goes away, but am not able to get the selected value in the code behind on button click (after selecting "1" in the dropdown, since for now I have registered only that value)
I get a runtime error - Unable to convert from string to double when I try accessing the selected value in drop down in code behind (The reason I believe is that no value is passed in the first place).
Any idea on what might be going wrong here!? Thanks!
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
Page.ClientScript.RegisterForEventValidation(Me.ddldobddId.UniqueID, "1")
MyBase.Render(writer)
End Sub
Protected Sub btnId_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnId.Click
If CType(Me.ddldobddId.SelectedValue, Integer) = 0 -> Throws the error
End Sub
You've pretty much got it. The DropDownList.SelectedValue is always going to be a System.String type.
You must convert the String to an Integer in your btnId_Click method.
Protected Sub btnId_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnId.Click
Dim convertedSelectedValue As Integer
convertedSelectedValue = Convert.ToInt32( Me.ddldobddId.SelectedValue )
End Sub

Add Multiple User Control of the Same Type to a Page

Similar questions to this one have been asked but none seem to address my exact situation here's what I am trying to do.
I have a user control that manages student info. i.e. FirstName, LastName, Address etc.
I have a webpage/form that has a button on it. "Add Student". What I want to accomplish is for a new StudentInfo control to be added to the webform after each click.
My current code looks something like this
Private Sub btnAddStudent_Click(sender as object, ByVal e As System.EventArgs)
Dim lStudentInfo as Control
LoadControl("~/StudentInfo.ascx")
Me.placeholder1.controls.add(lStudentInfo)
End Sub
With this code only one StudentInfo control is added and upon pressing the "Add" button again a new StudentInfo control isnt added below the first one and the text/data entered within the first control is cleared.
Thanks in advance for any assistance.
What is happening is that every time you do a postback your previous control was lost. Remember, every postback uses a brand new instance of your page class. The instance you added the control to last time was destroyed as soon as the http request finished — possibly before the browser even finished loading it's DOM.
If you want a control to exist for every postback you have to add it on every postback.
Additionally, if you want ViewState to work for the control you need to add it before the Load event for the page. This means either on Init or PreInit.
Private Sub btnAddStudent_Click(sender as object, ByVal e As System.EventArgs)
Me.placeholder1.controls.add(LoadControl("~/StudentInfo.ascx"))
Session("NewStudentControls") += 1
End Sub
Protected Sub Page_Init(sender as object, e as system.eventargs)
For i As Integer = 1 To Session("NewStudentControls")
Me.placeholder1.controls.add(LoadControl("~/StudentInfo.ascx"))
Next
End Sub

Resources