Examining the Project structure - ASP.NET Core 7 Part 4

ASP.NET Core 7: Examining the Project Structure



This is part 4 of the "Web App Development Beginners Guide" tutorial series. In this tutorial series, we will learn how to build a functional Web Application with individual account user login.

Part 4. ASP.NET Core 7: Examining the Project Structure

We are going to use the project we created in the first tutorial ASP.NET Core 7: Creating A Razor Pages Web Application: Step-by-Step Guide  In that, we used the ASP.NET Core Razor Web Page Application template to create the project. Figure 1 shows the project structure inside the Solution Explorer, where it displays the top-level folder structure.  It has 2 main files, 5 folders and two project items (Connected Service and Dependencies).


Figure 1:Solution Explorer -Top-level view

When using the wizard, there are a few options to choose from. The final generated project code and structure depend on these selections. For example, if a project is created using the ASP.NET Core 7 Web Application template, it will display Program.cs and appsettings.json files as well as three top-level folders: Pages, wwwroot, and Properties.

It also added two containers, which act as logical folders rather than physical ones. These containers are named Connected Services and Dependencies.

Since we utilized individual user authentication in the template wizard, the template wizard added two more folders with associated files to the project. These folders are named Areas and Data.

Figure 2 below shows the expanded view of the project in the Solution Explorer window.


Figure 2: Expanded view of the Project in the Solution Explorer window

Associated files and objects


Figure 3: Associated items

In Figure 3, above, all the items are expanded. When the `Index.cshtml` item is collapsed, Index.cshtml.cs file is hiding behind the index.cshtml file, it looks like a code-behind file. In Razor pages, any .cshtml.cs file acts as the controller for the .cshtml file. Again, if we expand the `index.cshtml` shows the index.cshtml.cs file underneath it. Both are physical files. If we expand the index.cshtml.cs it shows another child item, "IndexModel". This is not a file; it is a class view. This "IndexModel" can also be expanded and it shows the class' other child objects.

Also, appsettings.json and appsettings.Development.json are physical files. The appsettings.Development.json is to be used in development mode, so that developers can securely store user names and passwords for internet-related services, such as real email account login details for application testing. I will discuss this further when we learn about the appsettings.json file.

In summary, all the items shown inside marked green boxes in Figure 3, are physical files ( numbered 1 and 3). The items shown inside a marked red rectangle are NOT physical files; those are representing class objects in a graphical view.


Important Note!

Saving user secrets in the development environment 


Storing secrets, such as passwords or API keys, inside appsettings.json files in development projects is not recommended because these files are typically stored in plain text and can be easily accessed by anyone with access to the source code repository or the deployed application. This means that if these files are checked into version control or deployed to a production environment, the secrets can be exposed, which could lead to security breaches and data leaks.

Instead, secrets should be stored in a secure location, such as a key vault, that is accessible only to authorized personnel or applications. This helps to prevent unauthorized access and ensures that the secrets are only used by the application or service that needs them. Many cloud providers offer managed key vault services, which make it easy to securely store and retrieve secrets, without requiring the developer to manage their own infrastructure.

Additionally, it's essential to follow the principle of least privilege when granting access to secrets. Only the necessary permissions should be granted to the application or service that needs to use the secret, and these permissions should be reviewed periodically to ensure that they are still required.

In summary, storing secrets in appsettings.json files in development projects is not recommended because it can lead to security breaches and data leaks. Instead, secrets should be stored in a secure location, such as a key vault, and accessed only by authorized applications or personnel.


Program.cs

The Program.cs file is the starting point of any ASP.NET Core Web Application created using the template wizard. 

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using RazorPages.Core07.Identity.Data;
       
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration
	.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<applicationdbcontext>(options =>   options.UseSqlServer(connectionString));

builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    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();
app.Run();

  
Code 1: Program.cs


This is the application starting point. Initially, it configures the required services for the application, and then it defines all the necessary software modules in the application flow (pipeline) to handle requests and responses.

appsettings.json

appsetting.json file is the default settings file or some refer to it as a configuration file or application configuration settings file,  added when creating the Web Application project using the Template wizard. 
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-RazorPages.Core07.Identity-53bc9b9d-9d6a-45d4-8429-2a2761773502;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*"
}
Code 2: appsettings.json


This file is loaded during the host builder, as we can see in the above code, which contains the connection string and logging settings in JSON format. The default settings added to this file by the wizard depend on the template we select. In our case, as we selected user accounts, it added the connection string settings. If we use an empty project, it will only add logging settings, and so on.

Remember the important note above.

Folders added by the Template


The following figure shows the Windows Explorer folder structure of the project.


Figure 4: Physical project files in Windows File Explorer

Compare this folder as shown in Figure 4 with the Solution Explorer as shown in Figure 2


Connected Services


The Connected Service in Visual Studio 2022 is a feature that allows developers to easily connect their applications to external services, such as Azure, OpenAPI endpoints, gRPC (Remote Procedure Call) endpoints, Windows Communication Foundation (WCF) endpoints,  Databases and data providers.


Figure 5: Connected Services


It provides a simple and streamlined experience for configuring and consuming these services within the Visual Studio IDE. This can help developers save time and effort by automating many of the setup and configuration steps required to connect to external services.

Figure 5 shows the steps to open the connected service management window. Right-click on the"Connected Services" node in the Solution Explorer, marked as 1. Then select "Manage Connected Services", marked as 2, from the context menu.

Remember the important note above.

In Solution Explorer, under Properties, there is a file named serviceDependencies.json. When expanded, it reveals another file called serviceDependencies.local.json. These files are added by the wizard when configuring the connected services and are safe to check in since they do not contain any secrets.

Figure 6: Service Dependencies


wwwroot folder


This folder contains all the files related to the UI. The following expanded wwwroot folder shows the available files.


Figure 7: Expanded wwwroot folder

This is where we keep all static files for the web user interface(UI). The template uses Bootstrap v5.1.0 and jQuery JavaScript Library v3.6.0 in Visual Studio 2022. These files can be updated or add new libraries using the "client-side Library" tool. In addition to these files, all web site related images or image folders should be stored inside the wwwroot folder.

👍   As a rule of thumb, for the convenience of other developers:
  • Any new stylesheet that is required for customising the project should go under the CSS folder.
  • Any new javascript file required for customising the project should go under the js folder.
  • Alternatively, we have the option to employ a custom directory within the "wwwroot" folder—such as "Themes\MyTheme1"—wherein we can store various styles and script files. This arrangement also allows for the strategic organization of these files into distinct subfolders within the "Theme1" directory.
  • DO NOT put any custom file related to the project under the lib folder; use the lib folder for third-party client libraries only.

Figure 8: Top-level wwwroot folder items.

The website icon named favicon.ico is also located under the wwwroot folder. Visual Studio stores a default icon for us. We can change the website icon by replacing this file with our own logo. Remember the file should be named exactly as favicon.ico. If we want to use a different file name for this we need to modify the _Layout.cshtml file,  by adding this code to <head> section. remember to use the customer file location for the `href` value.

<link href="/images/custom-favicon.ico" rel="icon" type="image/x-icon"></link>
Code 3: favicon link


According to W3C, the format for the image you have chosen must be 16x16 pixels or 32x32 pixels, using either 8-bit or 24-bit colours. The image format must be one of PNG (a W3C standard), GIF, or ICO.

Areas

When using the ASP.NET Core Web application template, this folder and related files are added inside this folder only when the Individual User Accounts option is selected during the project setup wizard. This adds the identity framework related to _ViewStart.cshtml together with folder structure. If we use Identity Framework scaffolding to override defaults more folders and files will be added to the Identity subfolder in this Area folder.

Data

As the name implies this folder holds all the data-related files. This folder is also added when the Individual User Accounts option is selected during the project setup wizard. ASP.NET Core Identity Framework uses Microsoft Entity FrameworkCore. The following files are added:
  • ApplicationDbContext.cs
  • Migrations/00000000000000_CreateIdentitySchema.cs
  • Migrations/ApplicationDbContextModelSnapshot.cs

Pages

ASP.NET Core use the Pages folder to store all the Pages-related razor syntax files and supporting files. Each Razor page consists of two files in the format fileName.cshtml and fileName.cshtml.cs. 
  • A fileName.cshtml file is for HTML markup with C# code using Razor syntax.
  • A  fileName.cshtml.cs file is for C# code that handles page events similar to the code-behind concept.
The Template added the following  razor files:
  • Index.cshtml & Index.cshtml.cs
  • Privacy.cshtml & Privacy.cshtml.cs
  • Error.cshtml & Error.cshtml.cs

and the following supporting files (not paired with a .cs file):
  • _ViewStart.cshtml
  • _ViewImports.cshtml

Shared Folder

The Shared Folder in Razor Pages is used to contain all the view pages which need to be shared by other pages. e.g. layout files, other partial pages etc.
  • Shared/_Layout.cshtml
  • Shared/_LoginPartial.cshtml
  • Shared/_ValidationScriptsPartial.cshtml
If we need to add a cookie consent page, we can add it in the shared folder, for example, 
Shared/_CookieConsentPartial.cshtml

 We will take a look at some important files.

_Layout.cshtml

The  _Layout.cshtml file configures sitewide features common to all pages. This file sets up the sitewide scripts, stylesheets, navigation menu at the top of the page and the footer contents at the bottom of the page. The concept is similar to Master Pages in classic ASP.NETforms.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - RazorPages.Core07.Identity</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="~/RazorPages.Core07.Identity.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">RazorPages.Core07.Identity</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                    <partial name="_LoginPartial" />
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2023 - RazorPages.Core07.Identity - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <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> 
Code 4: _Layout.cshtml

_ViewStart.cshtml


This file indicates the layout file used for the application.

@{
    Layout = "_Layout";
}
Code 5: _ViewStart.cshtml


Code that needs to run before each view or page should be placed here. By convention, the _ViewStart.cshtml file is in the Pages folder. The statements listed in _ViewStart.cshtml are run before every full-page view (not layouts, and not partial views). _ViewStart.cshtml  and _ViewImports.cshtml(we will look at this file in the next section), are hierarchical. If a _ViewStart.cshtml file is located one or more levels down in the folder hierarchy, it will be run after the one defined in the root of the Pages folder.

_ViewImports.cshtml

This is a common file to specify namespaces to import. Razor directives shared by many pages are declared here. 
@using Microsoft.AspNetCore.Identity
@using RazorWebApp1
@using RazorWebApp1.Data
@namespace RazorWebApp1.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Code 5: _ViewImports.cshtml

  • The _ViewImports.cshtml file doesn't support other Razor features, such as functions and section definitions. 
  • A _ViewImports.cshtml file can be placed within any folder, in which case it will only be applied to pages within that folder and its subfolders.
  • _ViewImports.cshtml files are processed starting at the root level and then for each folder leading up to the location of the page or view itself. 
  • _ViewImports.cshtml settings specified at the root level may be overridden at the folder level.


_ViewStart.cshtml and _ViewImports.cshtml are not typically placed in the /Pages/Shared folder. The app-level versions of these files should be placed directly in the /Pages folder.

So this completes the "Part 4:  ASP.NET Core 7: Examining the Project Structure" tutorial. This tutorial is a valuable introduction for those new to ASP.NET Core and Visual Studio 2022 IDE.


This helps you familiarise yourself with ASP.NET Core Razor Pages Web Application in Visual Studio 2022 IDE.

To learn more details about the application we created, please look at the next article:




Comments

Popular posts from this blog

Getting Familiar with Visual Studio 2022 IDE - ASP.NET Core 7 Part 3

Displaying A Start Page In ASP.NET Core 3.1 Web API Project.