2. Our first ASP.NET Core project

2. Our first ASP.NET Core project

·

4 min read

What Tools are we using?

Before diving into the coding phase, it's important to note that I will be utilising two essential tools: Visual Studio and Microsoft SQL Server Management Studio. Both of these indispensable resources are not only freely available but can also be easily obtained through Microsoft's official websites.

Here are the details of the tools I'll be using:

  1. Visual Studio 2012 (Download)

  2. Microsoft SQL Server Management Studio 18 (Download)

  3. SQL Server Express LocalDB (Download)

These tools offer powerful capabilities for our development and database management needs while being conveniently accessible through Microsoft websites.

Project Planning

I've considered several key requirements, and I'd like to outline them here for clarity:

  1. Main UI Interface: The primary user interface will be a web portal. I will use Razor Pages in ASP.NET Core as it helps to focus coding on the page more easily. Learn more about Razor Pages.

  2. Multi-Tenancy Support: The system will support multi-tenancy, allowing for the management of various groups of applications to serve multiple organisations.

  3. Authentication and Authorization: Robust mechanisms for user authentication and authorization will be implemented.

It's important to note that this list, while comprehensive, is not exhaustive. I'm open to incorporating additional requirements as the project evolves and new needs arise.

Creating a New ASP.NET Core Project

Let's start by creating a new ASP.NET Core Web App project. Please follow these steps within Visual Studio:

  1. Launch Visual Studio.

  2. Select the project template as specified below when creating a new project.

  1. To configure the new project, set the project name as "Portal" and the solution name as "SimpleAppTest".

  2. Proceed by clicking the "Next" button to advance to the next stage. Set the Framework to ".NET 6.0" and keep the remaining settings at their default values.

  3. To ensure that the project is functioning correctly, press the F5 key to run it.

New Side Menu

Within the portal, we have three primary sections:

  1. Tenants: This section displays a list of organisations, where each organisation is referred to as a "tenant."

  2. Apps: Here, you can find a page listing applications associated with a specific tenant (organisation).

  3. Tests: This section provides a page listing smoke tests for a group of applications.

To enhance the portal's appearance, we will introduce a side menu that includes the following items:

  • Tenants

  • Apps

  • Tests

Fortunately, the project is already equipped with Bootstrap. To accomplish this, we can refer to a Bootstrap example known as the Dashboard from the Bootstrap website. This example features a side menu along with a top header.

Let's navigate to the _Layout.cshtml file, which can be found here.

Please replace the existing code in _Layout.cshtml file with the following:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Portal</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/Portal.styles.css" asp-append-version="true" />
</head>
<body>
    <header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
        <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" asp-page="/Index">Portal</a>
        <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="navbar-nav">
            <div class="nav-item text-nowrap">
                <a class="nav-link px-3" href="#">Sign out</a>
            </div>
        </div>
    </header>

    <div class="container-fluid">
        <div class="row">
            <nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block sidebar collapse">
                <div class="position-sticky pt-3">
                    <ul class="nav flex-column">
                        <li class="nav-item">
                            <a class="nav-link active" aria-current="page" href="#">
                                Tenants
                            </a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="#">
                                Apps
                            </a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="#">
                                Tests
                            </a>
                        </li>
                    </ul>
                </div>
            </nav>

            <main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
                @RenderBody()
            </main>
        </div>
    </div>

    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

Now, press F5 once more to run the project, and you should see the following layout.

Code Organization

Before we proceed to the next stage, I'd like to streamline the code organisation within our project. We've got two new features that are not only simple but also incredibly valuable, thanks to the release of ASP.NET Core 6 and C# 10.

ASP.NET Core 6 has introduced a simplified hosting model, designed to reduce the boilerplate code. On the other hand, C# 10 has introduced a nice feature known as File-Scoped Namespaces, where an entire file serves as the namespace's scope.

These features are personal favourites of mine as they significantly reduce boilerplate code. However, I still believe in the concept of a dedicated class for configuring services and pipelines, rather than lumping everything into the Program class.

Leveraging Extension Methods, I've relocated the service and pipeline configuration to a separate class named WebApplicationBuilderExtensions. As a result, our Program.cs file is now much cleaner and more organised.

Before:

After:

Content for WebApplicationBuilderExtensions.cs:

namespace Portal.Extensions;

public static class WebApplicationBuilderExtensions
{
    public static WebApplication ConfigureServices(this WebApplicationBuilder builder)
    {
        builder.Services.AddRazorPages();

        return builder.Build();
    }

    public static WebApplication ConfigurePipeline(this WebApplication app)
    {
        // Configure the HTTP request pipeline.
        if (!app.Environment.IsDevelopment())
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();

        app.MapRazorPages();

        return app;
    }
}

With this new organisational structure in place, we're well-prepared to proceed to the next stage.

Download source code

Github repository

Did you find this article valuable?

Support Han Chee by becoming a sponsor. Any amount is appreciated!