cshttp Tutorial - Day 1: Getting Started with cshttp

Back to cshttp Tutorial Main Menu

Day 1: Getting Started & Your First Multi-Page Website

Welcome! In this tutorial series, you will learn how to build real, interactive web applications using C#.

We will use cshttp — a high-performance, self-sustained, standalone micro web framework for C#. It lets you run web servers and create web apps with almost zero boilerplate or configuration.


1. Prerequisites (Choose Your Development Environment)

Before starting, choose ONE of the following two development setups:

Environment 1: Visual Studio (Community Edition - Recommended for Beginners)

Visual Studio provides a complete, all-in-one graphical development environment.

  • Download: https://visualstudio.microsoft.com/vs/community/
  • During Installation:
    • In the installer workloads screen, check ".NET desktop development" or "ASP.NET and web development".
    • In the Individual components tab, make sure .NET Framework 4.8 development tools and the latest .NET SDK (e.g., .NET 8 or newer) are selected.

Environment 2: Visual Studio Code + .NET SDK (Lightweight & Cross-Platform)

If you prefer a lightweight code editor:

  1. Install .NET SDK:
  2. Install VS Code:
  3. Install Extension:
    • Open VS Code, go to the Extensions tab (Ctrl + Shift + X), search for and install the official "C# Dev Kit" extension.

2. Getting cshttp into Your Project (3 Methods)

There are three ways to get cshttp into your project, depending on your preference:

Method 1: Download the Starter Pack (Easiest & Recommended)

Download the pre-configured cshttp-starter-pack.zip from the GitHub Releases page.

The Starter Pack is pre-configured to support both modern .NET (8.0, 9.0, 10.0+) and classic .NET Framework 4.8 automatically.

When you unzip the folder, you will see:

starter-pack/
├── lib/
│   ├── net8.0/               <-- Pre-compiled DLL for modern .NET
│   │   └── cshttp.dll
│   └── net48/                <-- Pre-compiled DLL for .NET Framework 4.8
│       └── cshttp.dll
├── StarterApp.csproj         <-- Pre-configured project (auto-detects runtime)
├── Program.cs                <-- Your application code
└── README.md

Everything is pre-wired. Open the folder, press run, and it works immediately.

Method 2: Manually Include the Pre-Compiled DLL

If you are creating a new project in Visual Studio or adding to an existing project:

  1. Create a Console App:
    • In Visual Studio, choose Create a new project. Search for Console and select Console App (.NET Framework) (or modern .NET Console App).

Search and select Console App in Visual Studio

  1. Configure Your Project:
    • Give your project a name, choose its directory, select .NET Framework 4.8 (or modern .NET), and click Create.

Configure project name, location and framework

  1. Grab the compiled cshttp.dll:
  2. Add Reference in Visual Studio:
    • In Solution Explorer, right-click References and select Add Reference...:

Right click References and select Add Reference

  • Click the Browse... button at the bottom:

Click Browse in Reference Manager

  • Navigate to cshttp.dll, select it, and click Add:

Select cshttp.dll and click Add

  • Make sure cshttp.dll is checked, then click OK:

Confirm cshttp.dll is selected and click OK

  • You will now see cshttp listed under References in Solution Explorer:

cshttp added under References in Solution Explorer

(Note: For modern SDK-style .csproj projects, you can alternatively copy cshttp.dll into a lib folder and add <Reference Include="cshttp"><HintPath>lib\cshttp.dll</HintPath></Reference> inside an <ItemGroup>.)

Method 3: Directly Include All Source Code

If you want complete control and want to step through cshttp's source code line by line while debugging:

  1. Clone or download the repository: https://github.com/adriancs2/cshttp.
  2. Either add the cshttp project (src\cshttp\cshttp.csproj) to your Solution and add a project reference, or copy the Core/, Web/, and Server/ source folders directly into your project.

3. Starting from Program.cs

Double-click Program.cs in Visual Studio via the Solution Explorer.

Here is what Visual Studio generates by default for a new console application:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {

        }
    }
}

Tip for beginners: You can safely ignore string[] args — it is used for command-line arguments when running an app from a terminal. In C#, both static void Main() and static void Main(string[] args) are valid entry points, so you can leave it as-is!

Now, let's initialize our web application!

  1. At the very top of the file, add using cshttp; to import the cshttp web framework.
  2. Inside Main(), call WebApp.Run(8080, OnRequest);.
  3. Create the OnRequest() method right below Main().
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using cshttp; // <-- 1. Import cshttp web framework

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 2. Start the web application on port 8080
            WebApp.Run(8080, OnRequest);
        }

        // 3. Define the request handler
        static void OnRequest()
        {
            
        }
    }
}

Understanding WebApp.Run(8080, OnRequest);

Let's look closely at the two parameters inside this line:

WebApp.Run(8080, OnRequest);
  1. 8080 (Port Number):

    8080 is the port number where your website will be listening. Once the program is running, you can open your web browser and visit your website at this address:

     http://localhost:8080
  2. OnRequest (Request Handler Method):

    The second parameter, OnRequest, routes every incoming HTTP request to our dedicated OnRequest() method. Behind the scenes, WebApp runs in a continuous loop, keeping your web application alive and always ready to call OnRequest() whenever someone visits your site.


4. Returning Your First Web Page ("Hello World")

Right now, OnRequest() is empty, so the server doesn't send anything back to the browser yet.

Next, what we want to do is return website content (HTML) to the user using Response.Write(html);:

using System;
using cshttp;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // Begin the web application
            WebApp.Run(8080, OnRequest);
        }

        static void OnRequest()
        {
            string html = @"
<html>
    <head>
        <title>Hello World</title>
    </head>
    <body>
        <h1>Welcome cshttp!</h1>
        <p>Hello World!</p>
    </body>
</html>
";
            Response.Write(html);
        }
    }
}

Run and See It!

  1. Press Start / Play in Visual Studio (or run dotnet run in your terminal).

Screenshot Visual Studio Press Run

Screenshot Visual Studio Press Run

  1. Open your browser and visit http://localhost:8080.
  2. You will see your very first web page: "Welcome cshttp! Hello World!"

(To stop the server at any time so you can edit code, click the Stop button in Visual Studio or press Ctrl + C in your terminal.)

Screenshot Browser Showing Webcome cshttp


5. Understanding URL Paths

In a real website, we normally have different addresses for different pages, such as:

http://www.mywebsite.com/
http://www.mywebsite.com/home
http://www.mywebsite.com/about
http://www.mywebsite.com/contact

Notice the ending part after the domain name. Above, we have 4 distinct pages:

PagePath
Root/
Home page/home
About page/about
Contact page/contact

In the web development world, this ending part is called the path.

When we are developing websites locally on our own computer, we don't have a custom domain name bound to it yet (such as www.mywebsite.com). Instead, the default domain for your own machine is always localhost.

Thus, on your browser and our WebApp server, those paths look like this:

http://localhost:8080/
http://localhost:8080/home
http://localhost:8080/about
http://localhost:8080/contact

6. Identifying the Path in Code

Now, let's go back to our code! We will expand OnRequest() to identify which path the user is currently browsing.

We can read the path using Request.Path.ToLower(), and use a standard C# switch statement to check it:

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();
            string html = "";

            switch (path)
            {
                case "/":
                case "/home":
                    break;
                default:
                    break;
            }
        }
    }
}

This is a standard, basic switch statement in C# to branch our logic based on path.


7. Returning Content for Each Path (and 404 Not Found)

Next, let's return the specific HTML content that we want to show the user for each path:

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();
            string html = "";

            switch (path)
            {
                case "/":
                case "/home":
                    html = @"
    <html>
        <head>
            <title>Hello World</title>
        </head>
        <body>
            <h1>Welcome cshttp!</h1>
            <p>Hello World!</p>
        </body>
    </html>
    ";
                    break;
                default:
                    Response.StatusCode = 404;
                    html = @"
    <html>
        <head>
            <title>Not Found</title>
        </head>
        <body>
            <h1>404 Not Found</h1>
            <p>The page that you are looking for does not exist.</p>
        </body>
    </html>
                ";
                    break;
            }

            Response.Write(html);
        }
    }
}

The code above handles the following paths:

http://localhost:8080/
http://localhost:8080/home
>> Shows the Home page ("Welcome cshttp!")

Any other path that is not defined in our switch statement, such as:

http://localhost:8080/about
http://localhost:8080/contact
http://localhost:8080/any-other-pages

will jump to the default: block, set Response.StatusCode = 404, and return the "404 Not Found" page!


8. Adding Support for /about and /contact

How do we add support for another path—let's say /about?

You simply add another case "/about": block inside the switch statement:

            case "/about":
                html = @"
    <html>
        <head>
            <title>About Us</title>
        </head>
        <body>
            <h1>About Us</h1>
            <p>It's Me!</p>
        </body>
    </html>
    ";
                break;

And we can do the exact same thing for /contact!

Here is what the complete code looks like when we put /, /home, /about, /contact, and the 404 page together:

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();
            string html = "";

            switch (path)
            {
                case "/":
                case "/home":
                    html = @"
    <html>
        <head>
            <title>Hello World</title>
        </head>
        <body>
            <h1>Welcome cshttp!</h1>
            <p>Hello World!</p>
        </body>
    </html>
    ";
                    break;
                case "/about":
                    html = @"
    <html>
        <head>
            <title>About Us</title>
        </head>
        <body>
            <h1>About Us</h1>
            <p>It's Me!</p>
        </body>
    </html>
    ";
                    break;
                case "/contact":
                    html = @"
    <html>
        <head>
            <title>Contact</title>
        </head>
        <body>
            <h1>Contact</h1>
            <p>Email us at [email protected]</p>
        </body>
    </html>
    ";
                    break;
                default:
                    Response.StatusCode = 404;
                    html = @"
    <html>
        <head>
            <title>Not Found</title>
        </head>
        <body>
            <h1>404 Not Found</h1>
            <p>The page that you are looking for does not exist.</p>
        </body>
    </html>
                ";
                    break;
            }

            Response.Write(html);
        }
    }
}

Why Start with .NET Framework Instead of Modern .NET Core?

You might wonder why this tutorial series starts with a .NET Framework project template rather than a modern .NET Core / .NET 8+ template.

In modern .NET Core templates, Microsoft introduced two "convenience" features enabled by default:

  • Top-Level Statements: The namespace, class Program, and static void Main(string[] args) are completely stripped away behind the scenes.
  • Implicit Usings: Standard namespaces like System, System.Collections.Generic, and System.IO are invisibly imported in background auto-generated files.

While convenient for experienced developers writing quick scripts, this often disorients beginners learning C# and web development:

  1. Understanding Code Architecture: Without the visible structure of namespace -> class -> method, learners cannot see where helper methods belong, how variable scope works, or how C# organizes real-world applications.
  2. Explicit is Better than Magic: Explicit using statements and defined class boundaries provide a clear, unambiguous blueprint of what code is running and where each feature comes from.
  3. Write Once, Run Anywhere: The code you write here is 100% universal C#. Once you master the structured foundation, your cshttp web applications will run identically whether compiled on .NET Framework 4.8 or deployed on modern .NET 8 / 10+!