Hey everyone,

I am a php programmer originally and am just helping a friend of mine update their website that they paid a designer (well that's what he called himself!) to do ages ago. I have built the whole site but am having problems on the most basic thing! I have a page which querys an MS SQL database and takes url variables to query it, so it takes the value of keyword= and perpage= (eg from www.site.com?keyword=test&perpage=15) to define a keyword to search for and the number of entries to display on a page. This works perfectly.

All i want is a very simple form (or whatever you want to call it) to pass these variables from another page on my site, so if it was an html form i would just have a form, a text box for the keyword and a pull down box with a few choices for perpage, then a submit button and a post method. Simple. All done.

I tried to do this within Visual Studio but discovered that as all aspx page are effectively forms you can't define another form within so this won't work. Then read up about asp buttons and text boxes and cross page postback (as it needs to send it to another page) and thought that was how to do it. I currently have (ignoring the pulldown box for the moment):
Keyword: <asp:textbox runat="server" id="txtKeyword"></asp:textbox> Per Page: <br />

<asp:button runat="server" id="buttonPost" Text="Click" PostBackUrl="search2.aspx?keyword=<%=txtKeyword.Text%>"></asp:button>

This cross posts to the correct page but just has <%=txtKeyword.Text%> as the keyword variable. I have read numerous methods of putting functions within the script tags of the page to read the variables, but i am using a master page so only have one script tag for all pages. I also read all asp buttons use get as their method? I have then read about using the Page.PreviousPage method to retrieve controls from the previous page, which i would rather not do as i want to just pass them simply through the url so as to allow for bookmarking specific searches etc. I am ultimately very confused and think i am missing something as i can't believe that there isn't a simple way of just passing the textbox values as variables through the url. :)

I would really, really appreciate any help anyone could give me, i've been messing about with this and reading up on it for ages and i am stumped, even though i completely appreciate i'm sure i'm being incredibly stupid and i really should have started at the beginning, as i say i'm just trying to help a friend of mine get his website back up.

Thank you so much for any help that you might be able to give, this is beginning to drive me crazy :),

Dave

Just use your old method. ASP.NET uses server tags in order to process forms VIA the server. And yes, you can only have one SERVER form tag on a page at a time, unless they are in panels which are visible or not.

You can have as many forms as you want on one page, but can only have one server-side form. Your search function does not need to be a server-side form as that you are just posting a querystring. Use the regular form with method "get" without a runat=server.

Use regular form, not runat server
<form method="get" action="selfordiffpage.aspx">

That's all. Just can only have one server-side form.

Oh, but asp controls are server-side form only. So use regular html form tags like <input> instead of asp:TextBox

Thanks so much for your reply, this is driving me absolutely crazy! That was what i tried as i assumed it would work, but the problem i'm having is it only seems to post to the current page, no matter what i do. I thought i couldn't do it because of the other form tag and that's why it was posting back to the same page, but as i say i really don't know anything about ASP.NET! I'm using a masterpage if that makes any difference? My code for the html form is:

<form method="get" action="search2.aspx">
Keyword: <input name="keyword"> Per Page: <select size="1" name="perpage"> <option value="5" selected="selected">5</option> <option value="10">10</option> <option value="15">15</option> <option value="20">20</option> <option value="25">25</option> <option value="30">30</option></select><br />
<input type="submit" value="Search" name="Submit"></form>

I would appreciate any ideas you could give so much, this is slowly turning me demented as it should be so easy, but i can't do it. I think i might have to shoot myself because there's just no point if i can't even work this out :)

Thanks so much mate,

Dave

Try this to see if it solves your problem. Might be that you are nesting a regular form into a server form, if you are hitting enter though. Try adding this to your submit button:

document.forms.formnamehere.submit();

I have a search function and it is similar to yours, and works. Try using the above one. and post back if you have any questions.

My apologies, i win the thicko prize, but when you say add it to your submit button, what exactly do you mean? Where within the button do you put it, do you use an OnClick method within the submit button or something?

Thanks so much,

Dave

Ok, i'm feeling less and less clever as this conversation goes on. In fact i think i might have to go and do an IT GCSE and learn how to turn a computer on. I have now put the following code into my page, which i think is what you meant:

<form name="testform" method="get" action="search2.aspx">
Keyword: <input name="keyword"> Per Page: <select size="1" name="perpage"> <option value="5" selected="selected">5</option> <option value="10">10</option> <option value="15">15</option> <option value="20">20</option> <option value="25">25</option> <option value="30">30</option></select><br />
<input type="button" onclick="document.forms.testform.submit();" value="Search" name="Submit"></form>

Unfortunately i get an error on page when i click on the Search button:

'document.forms.testform' is null or not an object

:( Any ideas?

Thanks so much, you are an absolute diamond,

Dave

sorry, it's javascript. Javascript doesn't do names, so what I meant by formname is formid. Just add the following line to your <form..> statement: id="testform"

It works on id's, not names. Most name attributes will eventually be obsolete. Anyway, just make sure the id of your form is now testform.

there's a quickway aruond this that I do not usually like, but works just fine. If you reference it into the current element, you can replace "document" with "this". So essentially, you can eliminate "document.forms.search.submit();" and put "this.form.submit();"

Anyway, I am not particularly fond of it, but it works just as well.

You can tell i'm an experienced asp.net programmer can't you :) Sorry, this is quite embarassing! :) I have made that change, but am still getting the same error as before. Here is my updated code:

<form id="testform" method="get" action="search2.aspx">
Keyword: <input name="keyword"> Per Page: <select size="1" name="perpage"> <option value="5" selected="selected">5</option> <option value="10">10</option> <option value="15">15</option> <option value="20">20</option> <option value="25">25</option> <option value="30">30</option></select><br />
<input type="button" onclick="document.forms.testform.submit();" value="Search" name="Submit" id="Button1"></form>

Thanks :),

Dave

Hey, i just tried the this.form.submit(); as a replacement within the last code i posted. I get no error this time, but instead it just posts back to the current page, rather than posting to the action page?

Thanks,

Dave

use this code:

<form name="testform" id="testform" method="get" action="search2.aspx">
Keyword: <input name="keyword" id="keyword"> Per Page: <select size="1" name="perpage" id="perpage"> <option value="5" selected="selected">5</option> <option value="10">10</option> <option value="15">15</option> <option value="20">20</option> <option value="25">25</option> <option value="30">30</option></select><br />
<input type="button" onclick="document.forms.testform.submit();" value="Search" name="Submit" id="Button1"></form>

I do not use masterpages and never have, so that MIGHT be the problem. Use the code above and it should work. If it doesn't I will try to search for an answer for you.

Sorry, what is the exact error you're getting? please let me know.

I tried using that code you just posted but i get the:

'document.forms.testform' is null or not an object

error on page again unfortunately :(......

Thanks so much for your help, it really is appreciated, you're preventing me from going completely crazy!

Dave

I have looked into it and it is due to the masterpages. Is there a way that you can design the search INTO the masterpage? Then you won't have a problem.

Otherwise, try trading out:
document.forms.testform.submit();

with:
this.form.submit();

Otherwise you can try writing a javascript function that will be called when pressing the search button.. but that is much harder

Master pages huh? ASP just makes everything so easy doesn't it :) I have tried using this.form.submit(); but then it posts to the current page rather than the one specified in action. I unfortunately can't integrate it into the master page as the search is totally specific to one section of the site and will make no sense if it's displayed on all pages.

I appreciate i have little to no knowlegde of ASP.NET so am not one to condemn it but why on earth have microsoft made such simple procedures so complicated. In pretty much every other web language in the world this is lesson 1. I have been trying to do this now for about 6 hours and i still can't. And whilst i'm extremely un asp proficient i am relatively experienced technically and programming wise so i wouldn't say i'm a novice. Just wondering if there's any reason or if it's the same reason you still can't make proper bullet point lists in word? :) I just can't believe there's no way of passing variables easily, i mean it's not exactly an unusual request is it? Gotta love MS.

Also presumably i'm right in thinking if you use javascript then anyone without javascript enabled won't be able to search? And as you say it's much more complicated. I think it might be time to kill myself :)

I found another suggested method which is:

<asp:textbox runat="server" id="txtKeyword"></asp:textbox><br />
<asp:textbox runat="server" id="txtKeyword2"></asp:textbox><br />
<asp:button runat="server" id="buttonPost" Text="Click" PostBackUrl="search2.aspx"></asp:button>

And then putting:

Request.Form("txtKeyword")
Request.Form("txtKeyword2")

into the page load in search2.aspx. The makes sense as an alternative (i think) if the one we're trying doesn't work, but i'm not sure where or how to specify the page load function on the search2.aspx page and wondered if you could tell me?

I am so so sorry for how absurd this, i cannot reiterate enough how much i appreciate your help, thank you,

Dave

Like I said, I do not use masterpages. Anyway, if by submitting the form normally (type=submit) just does a postback, then what you can do is do an if statement. It would run on page_load like the following:

Sub Page_Load
  Dim content As ContentPlaceHolder
  content = Page.Master.FindControl("ContentPlaceHolderName")

  Dim TextBox As TextBox 
  TextBox = content.FindControl("keyword").Text
  
  if TextBox <> "" or Not TextBox = Nothing then
    Dim DropDownList As DropDownList
    DropDownList = content.FindControl("perpage").Text
    response.redirect ("search2.aspx?keyword=" & TextBox & "&perpage=" & DropDownList & "")
  end if

Something like that should work as well if it does a postback.

ah okay that makes sense. Ok really really stupid question now, where do i actually put that page load function, it doesn't seem to like me putting into the .aspx.vb page and i can't put it in the <script> tags as they're within the master page?

Sorry evidently my degree didn't do me much good :)

Thanks....

if you use vb or vb.net, just follow the code below:

<script language="vb" runat="server">
Sub Page_Load
  Dim strKeyword As String = Request.QueryString("keyword")
  Dim intPerPage As Integer = Request.QueryString("perpage")

  if strKeyword <> = "" or Not strKeyword = Nothing then
    if intPerPage = "" or intPerPage = Nothing then
      intPerPage = "5" 'for results incase no perpage is specified.
    end if
    'you do not need the following line if you make the literal visible=false in the page.
    ltlErrorMessage.Visible = false
    'Now you can put it anyway you wish, into a datalist, repeater,
    'or grid. I would recommend a repeater, unless you need unlimited
    'functionality, then use datalist for it's control options.
  else
    'not necessarily needed, but extra isn't always bad!
    rpSearchResults.Visible = False
    ltlErrorMessage.Visible = true
    ltlErrorMessage.Text = "There were no keywords specified. Please try again."
  end if
End Sub
</script>

<html>
<body>
<asp:Repeater ID="rpSearchResults" runat="server>
<HeaderTemplate>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
</HeaderTemplate>
<ItemTemplate>
  <tr>
    <td><%# DataBinder.Eval(Container.DataItem, "field to show") %></td>
  </tr>
</ItemTemplate>
<SeparatorTemplate>
  <tr>
    <td><hr /></td>
  </tr>
</SeparatorTemplate>
<FooterTemplate>
</table>
</FooterTemplate>

</body>
</html>

oh, also with recent studies of the web users, there is 5% or less of users who disable javascript, so that shouldn't be that much of a problem! But in theory, yes you're correct. Without it, they won't be able to use that control.

Sorry still being thick, i can't have html and body tags within my search2.aspx page as they're within a masterpage which already defines them, which i think also means i can't have a <script> tag as well? Or am i missing something?

You are bloody impressive for three weeks, i personally think i have begun to experience what hell will be like:) An endless ASP.NET project for displaying data about Satan's ass. To be fair that's pretty much what i'm doing now. I must say i have never been convinced about the delights of php before, but god do i love it now, it's so sensible! :) And you can use a line or two to do something simple, rather than having to use fifty. :):)

Dave

you can still have the page load script. But keep in mind, if you have a page load for your masterpages, then you may have a conflict. but it doesn't seem as if you do. You should be fine, just lose the opening and ending basic html tags. and thank you!

I think i might cry! :)

I have tried integrating your code into my page, here is my entire search results page:

<%@ Page Language="VB" MasterPageFile="~/MasterPage2.master" AutoEventWireup="false" CodeFile="search3.aspx.vb" Inherits="search3" title="Search" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    <asp:Panel ID="Panel1" runat="server" BorderColor="#00AEEF" BorderStyle="Solid" Height="100%"
        ScrollBars="Vertical" Width="97.5%" HorizontalAlign="Left" CssClass="maincontents">



<script language="vb" runat="server">
Sub Page_Load
  Dim strKeyword As String = Request.QueryString("keyword")
  Dim intPerPage As Integer = Request.QueryString("perpage")

        If strKeyword <> "" Or Not strKeyword = Nothing Then
            If intPerPage = "" Or intPerPage = Nothing Then
                intPerPage = "5" 'for results incase no perpage is specified.
            End If
            'you do not need the following line if you make the literal visible=false in the page.
            ltlErrorMessage.Visible = False
            'Now you can put it anyway you wish, into a datalist, repeater,
            'or grid. I would recommend a repeater, unless you need unlimited
            'functionality, then use datalist for it's control options.
        Else
            'not necessarily needed, but extra isn't always bad!
            rpSearchResults.Visible = False
            ltlErrorMessage.Visible = True
            ltlErrorMessage.Text = "There were no keywords specified. Please try again."
        End If
End Sub
</script>

<asp:Repeater ID="rpSearchResults" runat="server">
<HeaderTemplate>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
</HeaderTemplate>
<ItemTemplate>
  <tr>
    <td><%# DataBinder.Eval(Container.DataItem, "field to show") %></td>
  </tr>
</ItemTemplate>
<SeparatorTemplate>
  <tr>
    <td><hr /></td>
  </tr>
</SeparatorTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>

</asp:Panel>
</asp:Content>

I get ltlErrorMessage not declared errors? Do i need to declare it in my aspx.vb page? I'm not entirely sure what you mean about making literal visible=false, is literal not another asp data container? All i really want is the keyword in a string that i can reference on the page!!!

God i can't believe how complicated this is turning out to be, again thank you so so much for spending your time helping me out, you are an absolute god send. Thank you.

Dave

ps: i added the </asp:Repeater> as Visual Studio kept telling me it should be there!

Check this little bit of genius (not thought up by me obviously!):

Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
        Response.Redirect("search2.aspx?keyword=" & txtKeywordxx.Text)
    End Sub

This takes the value of the textbox and places it as a variable in the url, just as i want. And in only 4 lines. I take back all the rude things i said about ASP and accept that i am just stupid :) I think i'm gonna stick to php after this :)

Thanks so so much for taking so much of your time to help me out on this one, it really really is appreciated, hopefully this might be helpful to you sometime

Dave :)

That works as well. And the reason why ltlErrorMessage isn't declared is because I never added it to the main page. So it was trying to find the Literal control with the id of ltlErrorMessage although there wasn't one on the page. If you wish, use this updated code.

<%@ Page Language="VB" MasterPageFile="~/MasterPage2.master" AutoEventWireup="false" CodeFile="search3.aspx.vb" Inherits="search3" title="Search" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    <asp:Panel ID="Panel1" runat="server" BorderColor="#00AEEF" BorderStyle="Solid" Height="100%"
        ScrollBars="Vertical" Width="97.5%" HorizontalAlign="Left" CssClass="maincontents">



<script language="vb" runat="server">
Sub Page_Load
  Dim strKeyword As String = Request.QueryString("keyword")
  Dim intPerPage As Integer = Request.QueryString("perpage")

        If strKeyword <> "" Or Not strKeyword = Nothing Then
            If intPerPage = "" Or intPerPage = Nothing Then
                intPerPage = "5" 'for results incase no perpage is specified.
            End If
            'you do not need the following line if you make the literal visible=false in the page.
            ltlErrorMessage.Visible = False
            'Now you can put it anyway you wish, into a datalist, repeater,
            'or grid. I would recommend a repeater, unless you need unlimited
            'functionality, then use datalist for it's control options.
        Else
            'not necessarily needed, but extra isn't always bad!
            rpSearchResults.Visible = False
            ltlErrorMessage.Visible = True
            ltlErrorMessage.Text = "There were no keywords specified. Please try again."
        End If
End Sub
</script>

<asp:Repeater ID="rpSearchResults" runat="server">
<HeaderTemplate>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
</HeaderTemplate>
<ItemTemplate>
  <tr>
    <td><%# DataBinder.Eval(Container.DataItem, "field to show") %></td>
  </tr>
</ItemTemplate>
<SeparatorTemplate>
  <tr>
    <td><hr /></td>
  </tr>
</SeparatorTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>

<asp:Literal ID="ltlErrorMessage" runat="server"><div style="color:#FF0000;font-family:Arial;font-size:11px;">Error: Sorry, there were no keywords found in that search. Please try again.</div></asp:Literal>

</asp:Panel>
</asp:Content>

And the reason why I didn't suggest that last bit of code first is because I didn't think you could reference the control directly through masterpages. I thought you had to find the content panel on the master page, then the control inside the content panel. Masterpages don't seem so threatening now that I know that works.. Then again, when I was trying to work with Masterpages, I was on ASP 1.1 which isn't for masterpages! That code works then, yes. Have you implemented it correctly? Everything works?

Sorry, now keep in mind that the code I just posted doesn't post results... you need to do these steps below to show results:
1. declare a connection, a database comand, and a reader
2. open the connection and run the database command.
3. execute the reader via ExecuteReader() style.
4. Bind the reader to the repeater you have on your page.

I use odbc so this example will show you what you need to know, but won't be exact: Here is the code you need to run the repeater exactly, but change out the variables you need to.

<%@ Page Language="VB" MasterPageFile="~/MasterPage2.master" AutoEventWireup="false" CodeFile="search3.aspx.vb" Inherits="search3" title="Search" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<asp:Panel ID="Panel1" runat="server" BorderColor="#00AEEF" BorderStyle="Solid" Height="100%"
ScrollBars="Vertical" Width="97.5%" HorizontalAlign="Left" CssClass="maincontents">

<script language="vb" runat="server">
Sub Page_Load
  Dim strKeyword As String = Request.QueryString("keyword")
  Dim intPerPage As Integer = Request.QueryString("perpage")

  If strKeyword <> "" Or Not strKeyword = Nothing Then
    If intPerPage = "" Or intPerPage = Nothing Then
      intPerPage = "5" 'for results incase no perpage is specified.
    End If
    Dim conPubs As OdbcConnection
    Dim cmdSelect As OdbcCommand
    Dim dtrReader As OdbcDataReader
	'For all the Dims above, you can code the lines below in to form less lines of code.
	'I don't like doing it as it looks messy and is problematic for me. Otherwise,
	'Delete the lines above and the lines below (where applicable) with these lines below this one.
	'Dim conPubs As New OdbcConnection( (System.Configuration.ConfigurationManager.AppSettings.Get("ConnectionString") )
	'Dim cmdSelect As New OdbcCommand( "SELECT * FROM Table WHERE fieldtocompare LIKE '" & strKeyword & "'", conPubs )	'conPubs.Open()
	'Dim dtrReader As OdbcDataReader = cmdSelect.ExecuteReader(CommandBehavior.CloseConnection)
	'
	'The line below references a connection set in the web.config
	'file in my site. It's better to use this kind of reference than to
	'manually put the connection in every time to reference it.
	conPubs = New OdbcConnection( System.Configuration.ConfigurationManager.AppSettings.Get("ConnectionString") )	cmdSelect = New OdbcCommand( "SELECT * FROM Table WHERE fieldtocompare LIKE '" & strKeyword & "'"", conPubs )
	conPubs.Open()
	dtrReader = cmdSelect.ExecuteReader()
	'another way to avoid having to close the conPubs connection at the
	'end of this code, substitute the next line for the one above
	'dtrReader = cmdSelect.ExecuteReader(CommandBehavior.CloseConnection)
	rpSearchResults.DataSource = dtrReader
	rpSearchResults.DataBind()
	dtrReader.Close()
	'if you substituted the dtrReader statements above, remove the line below
	conPubs.Close()
  Else
  'not necessarily needed, but extra isn't always bad!
  rpSearchResults.Visible = False
  ltlErrorMessage.Visible = True
  ltlErrorMessage.Text = "There were no keywords specified. Please try again."
  End If
  
  'The lines below just check if the connection is currently open,
  'and if it is, close it.
  If conPubs.State = ConnectionState.Open then
  conPubs.Close()
  end if
End Sub
</script>

<asp:Repeater ID="rpSearchResults" runat="server">
<HeaderTemplate>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# DataBinder.Eval(Container.DataItem, "field to show") %></td>
</tr>
</ItemTemplate>
<SeparatorTemplate>
<tr>
<td><hr /></td>
</tr>
</SeparatorTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>

<asp:Literal ID="ltlErrorMessage" runat="server"><div style="color:#FF0000;font-family:Arial;font-size:11px;">Error: Sorry, there were no keywords found in that search. Please try again.</div></asp:Literal>

</asp:Panel>
</asp:Content>

Now, when you take out all the comments, it won't be so much code, and will do wonders for tons of responses. If you're not familiar with SQL, I would add a limit on those return results, otherwise you can have thousands if your database is big enough, which means you would have a huge page..

after the very last bit of the SQL statement, add " LIMIT NumberOfRowsReturned". So LIMIT 10 would return 10 rows of results.

Wow, thanks! That code i printed before does indeed appear to do exactly what i need, parsing the variable via the url. I have just made a drop down box as a second input and have got that variable to be passed as well using the same method. It's like i'm using html forms again :)

Is there any reason that you know of why your method is better than the one i listed?

Dave

Nope. your method is better because you don't have to search all the code for a control. I thought with masterpages you had to use the FindControl() method. Since you don't, yours will be fine, if not better.

Oh, and in the above code, change out the "LIKE '" & strKeyword & "'"" with "LIKE '%" & strKeyword & "%'"

The reason for this is that the '%' allows room for errors. So if you have a keyword named "ame", it will pull all words that have "ame" in it that follow with or end with another letter, like "name" and "same". Understand? It's much better for searching!

If you have any other questions, I will answer them tomorrow morning, or if you're lucky, maybe one more time tonight. I haven't tested that code, but there should be no reason why it doesn't work. I hope I helped!

This article has been dead for over six months. Start a new discussion instead.