I am busy doing maintenance on an old VB.Net/ASP.Net solution.
Quite a number of the .aspx pages reference variables on the code behind. While working, these all show up as errors, but the code does compile (making it not critical, but extremely annoying, and difficult to find actual errors).
I have tried protected and private variables.
I made a test page, to indicate the proble.
TestForm.aspx
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="TestForm.aspx.vb" Inherits="EGS.TestForm" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<%=message %>
</div>
</form>
</body>
</html>
TestForm.aspx.vb
Public Class TestForm
Inherits System.Web.UI.Page
Protected message As String
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
message = "Hello!"
End Sub
End Class
Error List
Error | BC30451 | 'message' is not declared. It may be inaccessible due to its protection level.
Running it
Hello!
Is there a way to get Visual Studio (2015, if that makes a difference) to see these. They work just fine, like I said, it is just very annoying.
Use public modifier to declare the message variable
Public Class TestForm
Inherits System.Web.UI.Page
public message As String
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
message = "Hello!"
End Sub
End Class
Related
i am intend to override the function in my aspx, in my page , i have the follow register page
<%# Register TagPrefix="WebLITE" TagName="HeaderControl" Src="~/ctrl/HeaderControl.ascx" %>
<%# Register TagPrefix="WebLITE" TagName="FooterControl" Src="~/ctrl/FooterControl.ascx" %>
<%# Register TagPrefix="WebLITE" TagName="NavigationControl" Src="~/ctrl/NavigationControl.ascx" %>
<%# Register TagPrefix="WebLITE" TagName="FunctionTabControl" Src="~/ctrl/FunctionTabControl.ascx" %>
On the navigation page, there is a log out button, on the current page, i am intend to override that function, because there is some unique action i need to do during log out.
This is the source on the navigation page
Protected Sub Logout(ByVal sender As Object, ByVal e As System.EventArgs)
Session("LoggedIn") = Nothing
Session.Clear()
Session.Abandon()
Session.RemoveAll()
Response.Cookies("SessionId").Expires = DateTime.Now.AddDays(-30)
Response.Cookies.Add(New HttpCookie("SessionId", ""))
FormsAuthentication.SignOut()
Response.Redirect("~/login.aspx")
End Sub
what i did is put the following code in the page,
Public Overridable Sub Logout(ByVal sender As Object, ByVal e As System.EventArgs)
End Sub
However it seem does not working well, is there anyone can provide me the solution for this?
Lately i realized a problem in asp.net, which appears kinda strange to me.
I got an sample.aspx file:
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="sample.aspx.vb" Inherits="SampleProj.sample" MasterPageFile="~/Site.Master" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<input type="image" id="Accept" runat="server" class="accept-btn" src="/Images/accept.png" />
</asp:Content>
And the related codebehind file sample.aspx.vb:
Public Class sample
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Some code here
End Sub
Private Sub Accept_ServerClick(sender As Object, e As ImageClickEventArgs) Handles Accept.ServerClick
'Some code here
End Sub
So my Problem is easily explained: Upon clicking the accept button the Accept.ServerClick event is fired as expected, but for some reason (even though the page IS NOT reloaded) the Page.Load event is fired too. This is my first asp project and maybe this is an expected behaviour, but i found neither an explanation nor a way to disable it. Any information would be appreciated.
Greeting, Ohemgi
(If you find any errors this is caused by writing this short sample. My code is compiling and running without a problem, so my question is only about the load event)
That is perfectly fine. From MSDN Documentation:
After a page has been posted back, the page's initialization events (Page_Init and Page_Load) are raised, and then control events are processed.
If you do something in the Page_Load that you don't want to do every time you click a button, just wrap it inside this condition:
if (!Page.IsPostBack)
{
// Some code here. It is executed only once.
}
You can find more information in the links below:
ASP.NET Web Server Control Event Model
ASP.NET Page Life Cycle Overview
VB.Net version
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
' Some code here. It is executed only once.
End If
End Sub
Despite the firing of the method associated with a form and button click, my fileupload will not pass a value to a string, am I doing something obviously wrong (or just wrong in general)?
Do I need to attach a handler to the fileupload
Here is some sample source, note, it is the only code in the project, I have not made any definitions to the button or fileupload anywhere else:
Public Class WebForm1
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Protected Sub Button_Click()
Dim FileUpload1 As New FileUpload()
Dim X As String = FileUpload1.FileName
Response.Write(X)
End Sub
End Class
and the form:
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm1.aspx.vb" Inherits="Test.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button ID="Button1" runat="server" OnClick="Button_Click" text="Submit"/>
<%-- <input type="file" />--%>
</form>
</body>
</html>
After trying FileUpload.HasFile, it appears as though not only can I not get the file name (described to me in the answer below), but the FileUpload.HasFile is nothing when a file is associated with it as well, is there any reason for this?
Protected Sub Button_Click()
Dim FileUpload1 As New FileUpload()
'Dim X As String = FileUpload1.FileName
'Response.Write(X)
If (FileUpload1.HasFile) Then
' Do Something
' SaveFile(FileUpload1.PostedFile)
Else
End If
End Sub
If you are looking for the path of the uploaded file in the client's machine, that is not allowed for security reasons.
However you should be able to get just the file name using the FileName property.
I check the file name in my applications when i want to test the to see the filetype that is uploaded.
I do not think the following line is required in your Protected Sub Button_Click() function:
Dim FileUpload1 As New FileUpload()
That must be creating a new instance causing it to show you an empty File Name.
If you just need the file name and not the entire path you could try the above.
Edit: Just saw the edit to your questions. The line I asked you to remove may be causing HasFile property to be empty as well.
You can not pass/assign name asp:FileUpload, as it is converted to input type file it is not allowed due to security reason. As it could breach the security of client machine that is browsing the website. The only possibility to assign it a value is through user selection that is browsing and assigning the file by user from client (browser)
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.fileupload.saveas.aspx
You can use FileUpload.SaveAs method to save the selected file.
FileUpload1.SaveAs(savePath);
I'm new to ASP.NET but have quite a few successful test pages going now which I am using to slowly build up a new website and data application... hence my many questions on here.
Anyway, in my efforts to understand JSON, I have a test page trying to get the data out, but for some reason the script works fine when it's all one page, but not as code behind.
My ASPX file is:
<%# Page Language="VB" AutoEventWireup="false" CodeFile="json.aspx.vb" Inherits="jsonPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form runat="server">
Output:
<div id="readOut" runat="server"></div>
</form>
</body>
</html>
Code behind:
Imports Jayrock.Json.JsonTextWriter, Jayrock.Json, Jayrock.Json.Conversion, System.Net
Partial Class jsonPage
Inherits System.Web.UI.Page
Sub Page_Load(Sender As Object, E As EventArgs)
Dim cMessage As String = "{""ID"": 8291, ""Item"": ""Epiphone Les Paul Tribute Plus Outfit"", ""Main Image"": ""8291-113247"", ""Colour"": ""Vintage Sunburst"", ""Option"": ""none"", ""Price"": 549.0}"
Dim objResponse As JsonObject = CType(JsonConvert.Import(cMessage), JsonObject)
readOut.InnerText = "Item name is: " & objResponse("Item")
End Sub
End Class
As I say, this is just a test code to try to get to grips with JSON, the text "Item name is:" followed by the result of the JSON parsing, should be posted into the div id="readOut" in the main ASPX page, but it won't... the strange thing is that it works is I take out the Page_Load sub and run the code in the head of the ASPX file.
I've tried comparing this to other files I have that are working and can find no obvious reason why this is happening.
I think this may be your problem. I suspect you weren't even able to hit that code with a breakpoint?
Page_Load(Sender As Object, E As EventArgs)
Should have a handles clause.
Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
This is a really weird one - I will do my best to explain.
I have a basic master page:
<%# Master Language="VB" CodeFile="MasterPage.master.vb" Inherits="master_MasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
<asp:PlaceHolder ID="PH1" runat="server" />
<asp:PlaceHolder ID="PH2" runat="server" />
</div>
</form>
</body>
</html>
And a standard child page:
<%# Page Title="" Language="VB" MasterPageFile="~/master/MasterPage.master" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="master_Default" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
</asp:Content>
I have the following extension methods for finding controls recursively:
Option Strict On
Option Explicit On
Imports System.Runtime.CompilerServices
Imports System.Web.UI
Public Module ExtensionMethods
<Extension()> _
Public Function FindControlRecursively(ByVal parentControl As System.Web.UI.Control, ByVal controlID As String) As System.Web.UI.Control
If parentControl.ID = controlID Then
Return parentControl
End If
For Each c As System.Web.UI.Control In parentControl.Controls
Dim child As System.Web.UI.Control = FindControlRecursively(c, controlID)
If child IsNot Nothing Then
Return child
End If
Next
Return Nothing
End Function
<Extension()> _
Public Function FindControlIterative(ByVal rootControl As Control, ByVal controlId As String) As Control
Dim rc As Control = rootControl
Dim ll As LinkedList(Of Control) = New LinkedList(Of Control)
Do While (rc IsNot Nothing)
If rc.ID = controlId Then
Return rc
End If
For Each child As Control In rc.Controls
If child.ID = controlId Then
Return child
End If
If child.HasControls() Then
ll.AddLast(child)
End If
Next
rc = ll.First.Value
ll.Remove(rc)
Loop
Return Nothing
End Function
End Module
I have a control with a listview:
<%# Control Language="VB" AutoEventWireup="false" CodeFile="control-1.ascx.vb" Inherits="controls_control_1" %>
<p>
Control 1</p>
<asp:ListView ID="lv" runat="server">
<ItemTemplate>
<div>
<asp:Literal ID="Name" runat="server" Text='<%#Eval("Name") %>' />
<asp:LinkButton ID="TestButton" runat="server">Test</asp:LinkButton>
</div>
</ItemTemplate>
</asp:ListView>
That is databound:
Partial Class controls_control_1
Inherits System.Web.UI.UserControl
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Dim l As New List(Of Person)
Dim j As New Person
j.Name = "John"
l.Add(j)
lv.DataSource = l
lv.DataBind()
End If
End Sub
End Class
Public Class Person
Public Property Name As String
End Class
I have a second control that is very basic:
<%# Control Language="VB" AutoEventWireup="false" CodeFile="control-2.ascx.vb" Inherits="controls_control_2" %>
<p>Control 2</p>
In my child page, I have the following code to load the controls:
Option Strict On
Option Explicit On
Partial Class master_Default
Inherits System.Web.UI.Page
Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
Dim controlInstance1 As System.Web.UI.Control = LoadControl("~/controls/control-1.ascx")
controlInstance1.ID = "control_1"
Dim zone As System.Web.UI.Control = Me.Master.FindControlRecursively("PH1")
zone.Controls.Add(controlInstance1)
Dim controlInstance2 As System.Web.UI.Control = LoadControl("~/controls/control-2.ascx")
controlInstance2.ID = "control_2"
Dim zone2 As System.Web.UI.Control = Me.Master.FindControlRecursively("PH2")
zone2.Controls.Add(controlInstance2)
End Sub
End Class
This loads the controls, but if I click the Test button in the listview, the page loses the data in the listview after postback.
If I change the FindControlRecursively calls to FindControlIterative, when I click the test button, the data in the listview is retained after the postback.
Anybody have any idea what the FindControlRecursively call might be doing to cause the listview to lose it's data? This only happens if control-2 is added to the page - if it is not, and control-1 is loaded using FindControlRecursively, data is retained correctly after postback.
Thanks in advance...this one is driving me nuts, and it took me a while to figure out where exactly it was breaking down.
Why don't you simply expose properties that return PH1 and PH2, because the master has the reference of them and you don't need to iterate all child controls of master:
Public ReadOnly Property Container1 As PlaceHolder
Get
Return Me.PH1
End Get
End Property
Public ReadOnly Property Container2 As PlaceHolder
Get
Return Me.PH2
End Get
End Property
You can access them:
Dim ph1 As PlaceHolder = DirectCast(Me.Master, myMaster).Container1
Dim ph2 As PlaceHolder = DirectCast(Me.Master, myMaster).Container2
Another problem is this line:
controlInstance1.ID = "control_2"
You are setting only controlInstance1's ID twice, but that doesn't cause your issue.
Your main problem is that you are adding the controls to the placeholders in Page_Init instead of Page_Load. Therefore the UserControls can't load their ViewState and the ListView is empty. Recreate them in Page_Load and it will work.
Edit: But i must admit that i don't know why your iterate extension wins over the recursive. The reference on the placeholders are the same, they shouldn't work both, weird.
summary:
it works with my properties,
putting all in page's load event handler instead init
with your iterate-extension(for whatever reasons)
It also works if you add both UserControls at last, after you've found the placeholders via FindControlRecursively.
zone.Controls.Add(controlInstance1)
zone2.Controls.Add(controlInstance2)
I'm losing motivation on this, but i'm sure you'll find the answer here. Controls.Add loads it's parent's ViewState into all childs and therefore it depends on when you add the controls, also the index of the controls in their parent controls must be the same on postback to reload the ViewState.
Your recursive extension method touches control1's ID after you've added it to PH1(while searching PH2), the iterative extension does not. I assume that this corrupts it's ViewState in Page_Init.
Conclusion Use properties instead
I figured out why I was seeing the behavior I described above. I changed the recursive function to the following:
<Extension()> _
Public Function FindControlRecursively(ByVal parentControl As System.Web.UI.Control, ByVal controlId As String) As System.Web.UI.Control
If String.IsNullOrEmpty(controlId) = True OrElse controlId = String.Empty Then
Return Nothing
End If
If parentControl.ID = controlId Then
Return parentControl
End If
If parentControl.HasControls Then
For Each c As System.Web.UI.Control In parentControl.Controls
Dim child As System.Web.UI.Control = FindControlRecursively(c, controlId)
If child IsNot Nothing Then
Return child
End If
Next
End If
Return Nothing
End Function
By adding the parentControl.HasControls check, I am preventing the function from searching the listview for child controls, and this allows the listview to load its viewstate later on in the page/control lifecycle.
Also, I tweaked my iterative function to make it more efficient and prevent it from bugging out if a control was not returned:
<Extension()> _
Public Function FindControlIteratively(ByVal parentControl As Web.UI.Control, ByVal controlId As String) As Web.UI.Control
Dim ll As New LinkedList(Of Web.UI.Control)
While parentControl IsNot Nothing
If parentControl.ID = controlId Then
Return parentControl
End If
For Each child As Web.UI.Control In parentControl.Controls
If child.ID = controlId Then
Return child
End If
If child.HasControls() Then
ll.AddLast(child)
End If
Next
If (ll.Count > 0) Then
parentControl = ll.First.Value
ll.Remove(parentControl)
Else
parentControl = Nothing
End If
End While
Return Nothing
End Function
Also, to follow up on my earlier description of the problem - I was able to reproduce the recursive function's intially weird behavior using the iterative function if I removed the If child.HasControls() Then check from the iterative function. Hope that makes sense.
In the end I am sticking with the iterative function because looping should be less expensive than recursion, though in real world scenarios the difference probably will not be noticeable.
The following links were extremely helpful to me in working this out:
http://msdn.microsoft.com/en-us/library/ms972976.aspx#viewstate_topic4
https://web.archive.org/web/20210330142645/http://www.4guysfromrolla.com/articles/092904-1.aspx
http://scottonwriting.net/sowblog/archive/2004/10/06/162995.aspx
http://scottonwriting.net/sowblog/archive/2004/10/08/162998.aspx
Extra thanks to Tim for pointing me in the right direction.