cshttp Tutorial - Day 3: Accepting User Input (URL Query Strings & GET Forms)
Day 3: Accepting User Input (URL Query Strings & GET Forms)
In Day 1 and Day 2, our website only sent information from the server to the visitor.
Today, we will teach our web server how to accept input from the visitor so our website becomes truly interactive!
In Day 3, we will:
- Learn how URL Query Strings work (for example:
/greet?name=Alice). - Add a new
/greetroute to our router and navigation menu. - Read visitor parameters in C# using
Request.QueryString["name"]. - Build an interactive HTML
<form>so visitors can type their name into a text box and click a button to send it to our C# server.
1. Understanding URL Query Strings
Have you ever searched for something on Google or YouTube and noticed a question mark (?) in the browser's address bar?
https://www.google.com/search?q=csharp
http://localhost:8080/greet?name=Alice
Let's break down the two parts of http://localhost:8080/greet?name=Alice:
| Part | Value | Meaning |
|---|---|---|
| Path | /greet | Tells the server which page the visitor wants to open. |
| Query String | ?name=Alice | Sends extra data (a key-value pair) to that page! |
- The
?symbol marks the start of the query string. nameis the parameter key (variable name).Aliceis the value passed into that parameter.
If you want to pass more than one parameter in a URL, you separate them with an & symbol:
http://localhost:8080/greet?name=Alice&city=Seattle
2. Adding the /greet Page to Our Website
First, let's add a new /greet page to the code we wrote at the end of Day 2.
Step 1: Add /greet to OnRequest()
Inside OnRequest(), add case "/greet": to our switch statement so it calls HandleGreet():
static void OnRequest()
{
string path = Request.Path.ToLower();
switch (path)
{
case "/":
case "/home":
HandleHome();
break;
case "/greet": // <-- NEW: Route /greet to HandleGreet()
HandleGreet();
break;
case "/about":
HandleAbout();
break;
case "/contact":
HandleContact();
break;
default:
HandleNotFound();
break;
}
}
Step 2: Add the "Greet" Link to RenderPage()
Next, add <a href='/greet'>Greet</a> | to our <nav> bar inside RenderPage(). Because RenderPage() is our shared master template, this new link will immediately appear on every page:
static void RenderPage(string title, string bodyContent)
{
string html = $@"
<html>
<head>
<title>{title}</title>
</head>
<body>
<nav>
<a href='/'>Home</a> |
<a href='/greet'>Greet</a> |
<a href='/about'>About</a> |
<a href='/contact'>Contact</a>
</nav>
<hr />
{bodyContent}
<hr />
<footer>
<small>Server Time: {DateTime.Now:yyyy-MM-dd HH:mm:ss}</small>
</footer>
</body>
</html>";
Response.Write(html);
}
3. Reading the Query String in HandleGreet()
Now let's create the HandleGreet() method!
In cshttp, reading a query string parameter from the URL is just one line of code:
string name = Request.QueryString["name"];
Let's see what happens when a visitor opens /greet?name=Alice:
Request.QueryString["name"]returns"Alice".
What if a visitor just clicks the Greet link in the navigation menu (/greet) without ?name=... at the end?
Request.QueryString["name"]returnsnull(or an empty string""if they typed/greet?name=).
Let's write a simple version of HandleGreet() first to see how Request.QueryString["name"] works:
static void HandleGreet()
{
string name = Request.QueryString["name"];
string content = $@"
<h1>Interactive Greeting</h1>
<h2>Hello, {name}!</h2>";
RenderPage("Greet", content);
}
4. Handling Missing Input with string.IsNullOrEmpty()
Look closely at the simple HandleGreet() method above. If someone visits http://localhost:8080/greet without providing a name in the URL, {name} is blank, so the page will awkwardly display:
Hello, !
To make our page smarter, we can use C#'s built-in string.IsNullOrEmpty(name) method inside an if / else statement:
- If
nameis empty: Show a friendly prompt asking the user to enter their name, along with two quick test links (?name=Aliceand?name=Bob). - Else (
nameis provided): Show the personalized greeting!
Let's update HandleGreet() with this if / else check:
static void HandleGreet()
{
// 1. Read the "name" parameter from the URL (e.g. /greet?name=Alice)
string name = Request.QueryString["name"];
// 2. Decide what message to show using standard C# if/else
string greetingMessage = "";
if (string.IsNullOrEmpty(name))
{
greetingMessage = "<p>Please enter your name, or try clicking a quick link below!</p>";
}
else
{
greetingMessage = $"<h2>Hello, {name}! Welcome to C# Web Development!</h2>";
}
// 3. Display the greeting message and quick test links
string content = $@"
<h1>Interactive Greeting</h1>
{greetingMessage}
<p>Test query links directly:
<a href='/greet?name=Alice'>Greet Alice</a> |
<a href='/greet?name=Bob'>Greet Bob</a>
</p>";
RenderPage("Greet", content);
}
Try thinking through how those two links work:
- Clicking Greet Alice navigates the browser to
/greet?name=Alice. - Our C# server runs
HandleGreet(), seesnameis"Alice", and replies with "Hello, Alice! Welcome to C# Web Development!"
5. Adding an Interactive HTML <form>
Clicking pre-made links for Alice and Bob is neat, but what if the visitor wants to type their own name?
In HTML, we use a <form> element to create input boxes and submit buttons:
<form action='/greet' method='get'>
<label>Your Name:</label>
<input type='text' name='name' placeholder='Type your name...' />
<button type='submit'>Say Hello</button>
</form>
How Does This <form> Work?
Let's examine each important piece of this HTML form:
action='/greet':Tells the browser which URL path to send the data to when the user clicks the button.
method='get':Tells the browser to attach the form's input values directly onto the URL as a Query String (after a
?).<input type='text' name='name' ... />:Creates a text box. Notice
name='name'! Whatever attribute value you give toname='...'in HTML becomes the exact parameter key in the URL (?name=...), which matchesRequest.QueryString["name"]in our C# code!<button type='submit'>Say Hello</button>:When clicked, the browser takes what the user typed into the
<input>box (say,Charlie), combines it withaction='/greet', and automatically navigates to:http://localhost:8080/greet?name=Charlie
Let's add this <form> directly into HandleGreet():
static void HandleGreet()
{
// 1. Read the "name" parameter from the URL (e.g. /greet?name=Alice)
string name = Request.QueryString["name"];
// 2. Decide what message to show using standard C# if/else
string greetingMessage = "";
if (string.IsNullOrEmpty(name))
{
greetingMessage = "<p>Please enter your name below, or try clicking a quick link!</p>";
}
else
{
greetingMessage = $"<h2>Hello, {name}! Welcome to C# Web Development!</h2>";
}
// 3. Render both the message AND the form so they can try again
string content = $@"
<h1>Interactive Greeting</h1>
{greetingMessage}
<form action='/greet' method='get'>
<label>Your Name:</label>
<input type='text' name='name' placeholder='Type your name...' />
<button type='submit'>Say Hello</button>
</form>
<p>Or test query links directly:
<a href='/greet?name=Alice'>Greet Alice</a> |
<a href='/greet?name=Bob'>Greet Bob</a>
</p>";
RenderPage("Greet", content);
}
6. Complete Code for Day 3
Here is the complete Program.cs with everything we built today:
using System;
using cshttp;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
WebApp.Run(8080, OnRequest);
}
static void OnRequest()
{
string path = Request.Path.ToLower();
switch (path)
{
case "/":
case "/home":
HandleHome();
break;
case "/greet":
HandleGreet();
break;
case "/about":
HandleAbout();
break;
case "/contact":
HandleContact();
break;
default:
HandleNotFound();
break;
}
}
static void RenderPage(string title, string bodyContent)
{
string html = $@"
<html>
<head>
<title>{title}</title>
</head>
<body>
<nav>
<a href='/'>Home</a> |
<a href='/greet'>Greet</a> |
<a href='/about'>About</a> |
<a href='/contact'>Contact</a>
</nav>
<hr />
{bodyContent}
<hr />
<footer>
<small>Server Time: {DateTime.Now:yyyy-MM-dd HH:mm:ss}</small>
</footer>
</body>
</html>";
Response.Write(html);
}
static void HandleGreet()
{
// 1. Read the "name" parameter from the URL (e.g. /greet?name=Alice)
string name = Request.QueryString["name"];
// 2. Decide what message to show using standard C# if/else
string greetingMessage = "";
if (string.IsNullOrEmpty(name))
{
greetingMessage = "<p>Please enter your name below, or try clicking a quick link!</p>";
}
else
{
greetingMessage = $"<h2>Hello, {name}! Welcome to C# Web Development!</h2>";
}
// 3. Render both the message AND the form so they can try again
string content = $@"
<h1>Interactive Greeting</h1>
{greetingMessage}
<form action='/greet' method='get'>
<label>Your Name:</label>
<input type='text' name='name' placeholder='Type your name...' />
<button type='submit'>Say Hello</button>
</form>
<p>Or test query links directly:
<a href='/greet?name=Alice'>Greet Alice</a> |
<a href='/greet?name=Bob'>Greet Bob</a>
</p>";
RenderPage("Greet", content);
}
static void HandleHome()
{
string content = @"
<h1>Welcome cshttp!</h1>
<p>Click on <a href='/greet'>Greet</a> in the menu to test user input!</p>";
RenderPage("Home", content);
}
static void HandleAbout()
{
string content = @"
<h1>About Us</h1>
<p>It's Me!</p>";
RenderPage("About Us", content);
}
static void HandleContact()
{
string content = @"
<h1>Contact</h1>
<p>Email us at [email protected]</p>";
RenderPage("Contact", content);
}
static void HandleNotFound()
{
Response.StatusCode = 404;
string content = @"
<h1>404 Not Found</h1>
<p>The page that you are looking for does not exist.</p>";
RenderPage("404 Not Found", content);
}
}
}
7. Test It in Your Browser
- Run the application (
dotnet runor press Start in Visual Studio). - Open your browser and visit
http://localhost:8080/greet. - Click Greet Alice or Greet Bob and look at the browser's address bar (
http://localhost:8080/greet?name=Alice). - Now type your own name into the text box and click Say Hello.
- Notice how the browser automatically builds the URL
http://localhost:8080/greet?name=YourName, and your C# server reads it and personalizes the page for you!
In Day 4, we will upgrade our Contact page to use HTTP POST so visitors can submit longer messages and multi-field forms without cluttering the browser's URL bar.