cshttp Tutorial - Day 4: Handling Forms & Submissions (HTTP POST)
Day 4: Handling Forms & Submissions (HTTP POST)
In Day 3, we built an interactive form using method='get' (/greet?name=Alice).
Using GET puts all form inputs directly into the browser's URL address bar. That is great for search boxes or shareable links, where you want the search term in the URL.
However, what if a visitor is filling out a Contact Us form with their name, email address, and a multi-paragraph message (or a password)? We don't want a 500-word message or sensitive data appearing in the browser's URL bar!
For submitting forms, messages, and data, web standards use HTTP POST.
Today, we will:
- Understand the difference between HTTP GET and HTTP POST.
- Upgrade our
/contactpage from a static text page into an interactive Contact Form (method='post'). - Check
Request.HttpMethodso our/contactpage can handle both displaying the form (GET) and receiving the submitted form (POST). - Read submitted form fields using
Request.Form["fieldName"]and log them to the server console.
1. HTTP GET vs. HTTP POST
Whenever your web browser talks to a web server, every request includes an HTTP Method (also called an HTTP Verb) that tells the server what kind of action the browser is taking:
| HTTP Method | When the Browser Uses It | Where the Data Goes | Read in cshttp Using |
|---|---|---|---|
GET | Clicking a normal link, typing a URL in the address bar, or submitting a <form method='get'>. | Visible in the URL after ? (e.g., /greet?name=Alice). | Request.QueryString["key"] |
POST | Submitting a <form method='post'> by clicking its Submit button. | Hidden inside the background request body (the URL stays clean!). | Request.Form["key"] |
2. Starting from Our Current HandleContact() Method
Up through Day 3, our HandleContact() method simply displayed one line of static text:
static void HandleContact()
{
string content = @"
<h1>Contact</h1>
<p>Email us at [email protected]</p>";
RenderPage("Contact", content);
}
Let's replace that static text with a real HTML contact form!
3. Building the Contact Form (method='post')
Let's design a form with three input fields:
- Your Name (
<input type='text' name='sender' />) - Email Address (
<input type='email' name='email' />) - Message (
<textarea name='message'></textarea>)
Notice that we set method='post' on the <form> tag:
static void HandleContact()
{
string formContent = @"
<h1>Contact Us</h1>
<p>Send us a message below:</p>
<form action='/contact' method='post'>
<div>
<label>Your Name:</label><br />
<input type='text' name='sender' required style='width: 300px;' />
</div>
<br />
<div>
<label>Email Address:</label><br />
<input type='email' name='email' required style='width: 300px;' />
</div>
<br />
<div>
<label>Message:</label><br />
<textarea name='message' rows='5' cols='40' required></textarea>
</div>
<br />
<button type='submit'>Send Message</button>
</form>";
RenderPage("Contact", formContent);
}
Quick HTML Tips in This Form:
requiredattribute: Addingrequiredto an<input>or<textarea>tells the browser not to let the visitor submit the form if they left that box blank!type='email': Automatically checks that the user typed a valid email address format (containing an@symbol).<textarea>: Unlike<input type='text'>which is only a single line,<textarea>creates a multi-line text box for longer messages.
4. Detecting GET vs. POST with Request.HttpMethod
Look at the <form> we just wrote:
<form action='/contact' method='post'>
Because action='/contact' points to the exact same URL path (/contact), our HandleContact() method will be called in two different situations:
- Situation 1 (
GET): The visitor clicks Contact in the navigation bar to open the page. We want to show them the empty contact form. - Situation 2 (
POST): The visitor fills out the boxes and clicks Send Message. We want to read their submitted message and show a "Thank You" confirmation page.
How does HandleContact() know which situation is happening? We check Request.HttpMethod!
static void HandleContact()
{
if (Request.HttpMethod == "POST")
{
// Situation 2: The visitor clicked the Submit button!
return;
}
// Situation 1: Otherwise, it is a normal GET request (show the empty form)
string formContent = @"
...
";
RenderPage("Contact", formContent);
}
Why is there a
return;inside theifblock? Once we finish handling thePOSTsubmission and render the "Thank You" page,return;exitsHandleContact()immediately so C# doesn't continue downward and also render the empty form underneath!
5. Reading Submitted Data with Request.Form[...]
Now let's fill in the if (Request.HttpMethod == "POST") block!
In our HTML form, we gave our three inputs the following name='...' attributes:
name='sender'name='email'name='message'
When the form is submitted via POST, we read those exact names using Request.Form[...]:
string senderName = Request.Form["sender"];
string email = Request.Form["email"];
string message = Request.Form["message"];
Let's also print the message to our C# server console using Console.WriteLine(...) so you can watch messages arrive live in your terminal window, and then render a personalized "Thank You" page back to the visitor:
static void HandleContact()
{
// If the user clicked the Submit button, the browser sends a POST request
if (Request.HttpMethod == "POST")
{
string senderName = Request.Form["sender"];
string email = Request.Form["email"];
string message = Request.Form["message"];
// Print to the C# server console so you see it arrive live in your terminal!
Console.WriteLine($"[New Message] From: {senderName} ({email}) - {message}");
string thankYouContent = $@"
<h1>Thank You, {senderName}!</h1>
<p>We received your message and will reply to <b>{email}</b> soon.</p>
<div style='background: #f0f0f0; padding: 10px; border-radius: 4px;'>
<i>""{message}""</i>
</div>
<p><a href='/contact'>Send another message</a></p>";
RenderPage("Message Received", thankYouContent);
return;
}
// Otherwise, it's a GET request: Display the empty contact form
string formContent = @"
<h1>Contact Us</h1>
<p>Send us a message below:</p>
<form action='/contact' method='post'>
<div>
<label>Your Name:</label><br />
<input type='text' name='sender' required style='width: 300px;' />
</div>
<br />
<div>
<label>Email Address:</label><br />
<input type='email' name='email' required style='width: 300px;' />
</div>
<br />
<div>
<label>Message:</label><br />
<textarea name='message' rows='5' cols='40' required></textarea>
</div>
<br />
<button type='submit'>Send Message</button>
</form>";
RenderPage("Contact", formContent);
}
6. Complete Code for Day 4
Here is the complete Program.cs with our upgraded HandleContact() method:
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);
}
// NEW IN DAY 4: Handling both GET (show form) and POST (receive form)
static void HandleContact()
{
// If the user clicked the Submit button, the browser sends a POST request
if (Request.HttpMethod == "POST")
{
string senderName = Request.Form["sender"];
string email = Request.Form["email"];
string message = Request.Form["message"];
// Print to the C# server console so you see it arrive live in your terminal!
Console.WriteLine($"[New Message] From: {senderName} ({email}) - {message}");
string thankYouContent = $@"
<h1>Thank You, {senderName}!</h1>
<p>We received your message and will reply to <b>{email}</b> soon.</p>
<div style='background: #f0f0f0; padding: 10px; border-radius: 4px;'>
<i>""{message}""</i>
</div>
<p><a href='/contact'>Send another message</a></p>";
RenderPage("Message Received", thankYouContent);
return;
}
// Otherwise, it's a GET request: Display the empty contact form
string formContent = @"
<h1>Contact Us</h1>
<p>Send us a message below:</p>
<form action='/contact' method='post'>
<div>
<label>Your Name:</label><br />
<input type='text' name='sender' required style='width: 300px;' />
</div>
<br />
<div>
<label>Email Address:</label><br />
<input type='email' name='email' required style='width: 300px;' />
</div>
<br />
<div>
<label>Message:</label><br />
<textarea name='message' rows='5' cols='40' required></textarea>
</div>
<br />
<button type='submit'>Send Message</button>
</form>";
RenderPage("Contact", formContent);
}
static void HandleGreet()
{
string name = Request.QueryString["name"];
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>";
}
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>Visit <a href='/contact'>Contact</a> to test submitting an interactive POST form!</p>";
RenderPage("Home", content);
}
static void HandleAbout()
{
string content = @"
<h1>About Us</h1>
<p>It's Me!</p>";
RenderPage("About Us", 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/contact. - Fill out Your Name, Email Address, and Message, then click Send Message.
- Notice two important things:
- Your browser shows the personalized "Thank You" confirmation page, while the URL in the address bar stays cleanly at
http://localhost:8080/contact(no messy?sender=...in the URL!). - Look at your black console / terminal window where the server is running—you will see
[New Message] From: ...printed live on your screen!
- Your browser shows the personalized "Thank You" confirmation page, while the URL in the address bar stays cleanly at
In Day 5, we will take user submissions one step further: instead of just printing messages to the console, we will store them in server memory (List<string>) to build a live Community Guestbook where visitors can see everyone's posted comments!