Got Questions?

Get the Help You Need

asp:Q&A

LANGUAGES: VB.NET

ASP.NET VERSIONS: 1.x

 

Got Questions?

Get the Help You Need

 

By Josef Finsel

 

Welcome to the new asp:Q&A column. To get things started, I ll answer several questions I received this month about forms and processing. But before I get to those, I want to remind you that this is your column it runs on the questions you ask, so feel free to send them my way so I can help you.

 

Q. How can I disable the Submit button once it has been clicked, so a user can t click on it repeatedly? I tried buttonName.Enabled = false, but that doesn t seem to work.

 

A. This is a tricky one. To understand why the obvious doesn t work, you need to understand how the code is processed. The click event happens before the submit event, so disabling the button makes it invisible to the server, and thus the server cannot process the submit command. So we need to disable the button somewhere else. In this case, the easiest way to do it is by using JavaScript in the onsubmit event for the form. You can see how this works with the following code snippet:

 

<form id="Form1" method="post" runat="server" onsubmit=

"Form1.btnSubmit.disabled=true;alert('See');

action="WebForm2.aspx">

 

I used the alert on purpose to delay loading the new form so that you can see that the button is indeed disabled which provides a nice segue into the next question ...

 

Q. Once a user has submitted information and moved on to a new page, how do I keep the user from returning to the original page and resubmitting that information?

 

A. You can t really prevent them from returning to the page, but you can modify the page so that they can t resubmit the information. There are several methods you can use to do this, depending on how much work you want to do, but all are variations on checking a session variable in the Page_Load event for a variable that you fill in with data when the form is submitted. If the variable contains data, then you don t let them fill in the form. You can do this by disabling all the controls in the form and telling them that they have already filled in the form, or you can redirect them to a secondary page that tells them that message and then sends them to the page to which you want them to go. The following code fragment demonstrates this concept:

 

If Not Page.IsPostBack() Then

   If Session.Item("Name") Is Nothing Then

  Response.Redirect("AlreadyFilledIn.aspx?destination=

                    WebForm2.aspx")

   End If

End If

 

In this case, it sends the user to an error page that tells them they have already filled in the page and offers a link back to the appropriate page in this case the one to which they would have posted their original data. The AlreadyFilledIn page contains nothing more than a literal tag that gets filled in on page load to tell the user that they have already filled in the form they are trying to access, and then provides a link to the destination specified in the query variable passed to it. The full code for the sample for these two questions and the error page can be found in the accompanying download file; see end of article for details.

 

Q. Here s the situation: I have two dropdown boxes. Each is loaded from a table, and the tables are in a one-to-many relationship. The contents of the second dropdown box changes depending on the selection in the first. Is there any way I can load all the data from the child table into memory just once, then query that data when the selection in the first dropdown box changes?

 

A. The easiest way to handle this is with a session variable, as shown in Figure 1. In its simplest form, the code is loading two data tables with data; the first with information from the author s table in pubs and the second with a list of all of the books with author identifier. Then the second data table is filtered to show only the books for the currently selected author.

 

Private Sub Page_Load(ByVal sender As System.Object,

                     ByVal e As System.EventArgs)

                     Handles MyBase.Load

 'Put user code to initialize the page here

 Dim cn As SqlClient.SqlConnection = New _

    SqlClient.SqlConnection("server=localhost;uid=sa;

                           pwd=;database=pubs;")

 Dim sdAuthors As SqlClient.SqlDataAdapter = _

   New SqlClient.SqlDataAdapter("select au_lname + ',' +

                                au_fname as name, au_id

                                from pubs..authors order

                                by au_lname", cn)

 Dim sdTitles As SqlClient.SqlDataAdapter = _

    New SqlClient.SqlDataAdapter("select b.title, b.title_id,

                                 a.au_id from titleauthor a

                                 join titles b on

                                a.title_id =

                                b.title_id", cn)

 Dim dtAuthors As Data.DataTable

 Dim dtTitle As Data.DataTable

 Dim ds As DataSet = New DataSet()

 Dim filterOn As String

 If Not Page.IsPostBack() Then

   sdAuthors.Fill(ds, "Authors")

   sdTitles.Fill(ds, "Titles")

   dtAuthors = ds.Tables("Authors")

   dtTitle = ds.Tables("Titles")

   listOfAuthors.DataSource = dtAuthors.DefaultView

   listOfBooks.DataSource = dtTitle.DefaultView

   listOfAuthors.DataTextField = "Name"

   listOfAuthors.DataValueField = "au_id"

   listOfBooks.DataTextField = "title"

   listOfBooks.DataValueField = "title_id"

   listOfAuthors.DataBind()

   Session.Add("Titles", dtTitle)

   filterOn = "au_id = '" &

    listOfAuthors.SelectedItem.Value.ToString() & "'"

   dtTitle.DefaultView.RowFilter = filterOn

   listOfBooks.DataBind()

 Else

   listOfBooks.ClearSelection()

   dtTitle = Session("Titles")

   listOfBooks.DataSource = dtTitle.DefaultView

   filterOn = "au_id = '" &

    listOfAuthors.SelectedItem.Value.ToString() & "'"

   dtTitle.DefaultView.RowFilter = filterOn

   listOfBooks.DataBind()

 End If

End Sub

Figure 1: Saving data to the session variable.

 

If the page is posted back, the listOfBooks control is first cleared, then the data is filtered again and redisplayed in the dropdown box. A quick look at SQL Profiler will prove that the database is only being hit once for the page load, and subsequent hits are using data from memory. While this is an effective solution for this example, it does have some drawbacks that need to be considered. Based on the pubs database, the title of a book can be up to 80 characters long; the length of the title id and author id is an integer, which is 4 bytes long, and there are 25 records, so we could require up to about 2KB of memory for each user who is accessing the page. This is not a large amount of memory, but if you had either a larger dataset populating the dropdown box or a large number of simultaneous users, you might consider using data islands, which would allow multiple users to use the same resource (in this case, a list of books).

 

That s it for this month. Send your ASP.NET questions to [email protected] so I can help get you the answers you need.

 

The sample code accompanying this article is available for download.

 

Josef Finsel is a software consultant. He has published a number of VB and SQL Server-related articles and is currently working on the syntax for FizzBin.NET, a programming language that works the way programmers have always suspected. He s also author of The Handbook for Reluctant Database Administrators (Apress, 2001).

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish