ASP.NET Basics
Translated from German using DeepL and ChatGPT.
Date: August 2022
Reading time: 12 minutes
This blog post, explains what ASP.NET is and what types of projects can be created with it.
.NET
.NET is a development platform by Microsoft for building apps. The framework is free, cross-platform, open-source, object-oriented, and is considered one of the most efficient today.
Key Facts
Initial Release Date: End of 2000
Developer: Microsoft
Current Version: 6.0.3
Programming Languages: C#, F#, Visual Basic, C++
ASP.NET
ASP.NET (Active Server Pages Network Enabled Technologies) is a web framework for creating dynamic HTML, CSS, and JS web apps, applications, and services. It has been available since 2002.
The advantages of ASP.NET include:
- Reduced development time
- Out-of-the-box features
- Simplicity
- Security
- Customizability
- ...
ASP.NET applications consist of two files:
The Program.cs
configures, builds, and starts the application.
The appsettings.json
file contains the configuration, including allowed hosts, logging information, and connection strings. These values are used in Program.cs
but can also be accessed by models.
Learning
If questions arise about specific points regarding ASP.NET, they can usually be clarified quickly.
For beginners, the Microsoft tutorials in video format are recommended: https://dotnet.microsoft.com/en-us/learn/aspnet (opens in a new tab)
Models
When creating a project in Visual Studio, you'll encounter several options. In this section, I'll explain each model.
Web Forms
Documentation: https://docs.microsoft.com/en-us/aspnet/web-forms/ (opens in a new tab)
What is Web Forms?
Web Forms applications are called through the browser. Pages are written with HTML, client-side scripts, server controls, and server code. Upon request, everything is compiled and executed by the framework.
A Web Form page consists of a file for both code and markup. In Visual Studio, Web Forms development is very user-friendly, which is its biggest advantage. Elements can be dragged and dropped, and pages can be edited via an editor. It's also easy to set properties, methods, and events.
However, Web Forms is rarely used today. The approach is outdated, and tutorials are mostly obsolete.
Installation
When creating a new project, you need to select the appropriate template.
In a later step, you can choose Web Forms.
If Web Forms is not listed, you need to install two things under ASP.NET web development
:
- .NET Framework project and item templates
- Additional project templates
MVC
Documentation: https://docs.microsoft.com/en-us/aspnet/core/mvc/overview?view=aspnetcore-6.0 (opens in a new tab)
Tutorial: https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/start-mvc?view=aspnetcore-6.0&tabs=visual-studio (opens in a new tab)
What is MVC?
MVC is a widely used pattern that divides the project into Models, Views, and Controllers.
The big advantage is that you can create both GUIs and APIs within the same project. MVC is the modern project type and has been around the longest. Because of this, there are many projects that follow this approach.
Installation
Example
This example demonstrates what is needed to display a page.
Often forgotten is that MVC doesn't consist of just three parts. A request must first be routed to a controller.
In ASP.NET, routing can be found in Program.cs
.
This file describes how the URL should look when the page is called.
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
If the request is sent with the URL /Home/Index/2
, the Index
method in the HomeController
will be executed with the parameter 2
.
Here, we assume a URL like /Welcome/kay/3
. It's important to adjust the route accordingly.
using Microsoft.AspNetCore.Mvc;
namespace MvcMovie.Controllers
{
public class HelloWorldController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult Welcome(string name, int numTimes = 1)
{
ViewData["Message"] = "Hello " + name;
ViewData["NumTimes"] = numTimes;
return View();
}
}
}
After the code in the Welcome
method is executed and ViewData
is filled, the View
method is called, which renders the corresponding view.
@{
ViewData["Title"] = "Welcome";
}
<h2>Welcome</h2>
<ul>
@for (int i = 0; i < (int)ViewData["NumTimes"]!; i++)
{
<li>@ViewData["Message"]</li>
}
</ul>
In the view, besides the HTML, the @
symbol is used to inject C# code.
In this case, a loop is used to display the name multiple times.
Model
In MVC, there are several useful features related to the model.
Entity Framework
When working with models, it's also useful to use Entity Framework (EF).
EF allows you to generate a database from the code or generate code based on an existing database. There are two approaches: Model First and DB First. Since I am using the Model First approach in my current project, I will explain this here.
I first created the corresponding models. After that, I used the Package Manager Console to create and apply a migration.
Add-Migration InitialCreate
Update-Database
Line 1 generates a Migrations/{timestamp}_InitialCreate.cs
file.
Line 2 uses the generated migration to update the database.
Context
A Context
class was created during the process.
This class contains the DbSet<Nistbox.Models.Nistbox>
properties, which represent the data in the database.
The project is about birdhouses (Nestboxes).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Nestbox.Models;
namespace Nestbox.Data
{
public class NestboxContext : DbContext
{
public NestboxContext (DbContextOptions<NestboxContext> options)
: base(options)
{
}
public DbSet<Nestbox.Models.Coordinates>? Coordinates { get; set; }
public DbSet<Nestbox.Models.Log>? Log { get; set; }
public DbSet<Nestbox.Models.Nestbox>? Nestbox { get; set; }
}
}
Dependency Injection
The NestboxContext
can be used in controllers via Dependency Injection (DI).
private readonly NistboxContext _context;
public NistboxesController(NistboxContext context)
{
_context = context;
}
To enable this, the following code was added to Program.cs
.
builder.Services.AddDbContext<NistboxContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("NistboxContext") ??
throw new InvalidOperationException("Connection string 'NistboxContext' not found.")
)
);
Connection String
To establish a connection to the database, a connection string is needed.
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-Nestbox-CONNECTION-KEY;
Trusted_Connection=True;MultipleActiveResultSets=true",
"NistboxContext": "Server=(localdb)\\mssqllocaldb;Database=Nestbox.Data;Trusted_Connection=True;
MultipleActiveResultSets=true"
},
Initial Create
This file is responsible for creating the data in the database.
// ...
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<float>(
name: "Longitude",
table: "Coordinates",
type: "real",
nullable: false,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AlterColumn<float>(
name: "Latitude",
table: "Coordinates",
type: "real",
nullable: false,
oldClrType: typeof(int),
oldType: "int");
}
// ...
Alternatives
As mentioned earlier, there is also the DB-First approach. With this approach, you first create the tables in the database and then generate the code from them.
You can read more about it here: https://docs.microsoft.com/en-us/ef/ef6/modeling/designer/workflows/database-first (opens in a new tab)
View
C# Code
As mentioned earlier, C# code can be written in views. This opens up a lot of possibilities. More information can be found in the documentation: https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/views/ (opens in a new tab)
Partial Views
Another advantage of MVC is that it allows for clean views, where the data only needs to be displayed. However, such views can become very large and hard to manage.
To avoid this, parts of a view can be outsourced. This is done by default.
To understand how, you can look at the layout file. It contains @RenderBody()
, which inserts the content of the page into the layout.
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
Such partial views can be identified by the horizontal lines.
You can also create and integrate your own partial views.
@Html.Partial("_NavBar")
Controller
In controllers, you can do a lot. It's also important how you communicate with the view. This section explains how to do this.
Passing Data into Views
When logic is handled in the controllers and needs to be displayed in the views, the question arises: how can you pass data into the views?
There are several ways to do this.
ViewData["Movie"] = movie;
return View();
<h2>@( ((Movie) ViewData["Movie"]).Name )</h2>
View Method
Later, you can pass the value directly via the View
method.
return View(movie);
<h2>@Model.Name</h2>
ViewBag
The issue with the previous two methods is that passing multiple data values can be cumbersome. Therefore, ViewBag is used.
ViewBag.Title= "Hello World";
return View();
<h2>@ViewBag.Title</h2>
Action Results
View
is just one of the helper methods. Here are a few more.
namespace Vidly.Controllers
{
public class MoviesController : Controller
{
// GET: Movies
public ActionResult Random()
{
var movie = new Movie() { Name = "Shrek" };
return View(movie);
//return Content("Hello Wolrd");
//return HttpNotFound();
//return new EmptyResult();
//return RedirectToAction("Index", "Home", new { page = 1, sortBy = "name" });
}
}
}
Blazor
Documentation: https://docs.microsoft.com/en-us/aspnet/core/blazor/?WT.mc_id=dotnet-35129-website&view=aspnetcore-6.0 (opens in a new tab)
Tutorial: https://dotnet.microsoft.com/en-us/learn/aspnet/blazor-tutorial/intro (opens in a new tab)
Website: https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor (opens in a new tab)
What is Blazor?
Blazor distinguishes between two types of project.
On the one hand, there is Blazor Server. Blazor Server is extremely unique. It combines server-side and client-side rendering. This means that it can put together the
pages very quickly, but still remains very interactive. The user therefore receives the website quickly and can also add elements, such as
in React or Angular. C# is used as the front-end language instead of JS. The markup and
code is written in Razor files.
This combination of server-side and client-side rendering makes Blazor Server one of the fastest projects.
However, there is also Blazor WebAssembly. Such projects are only loaded on the client side. In addition, WebAssembly applications are poorly protected
. You are therefore not allowed to use keys, establish direct database connections and not even the appsettings file is
desired. If you want to work with data, an additional API is required.
In addition to these disadvantages, there is also an important reason to use it. Such projects can be used offline after a download of approx. 10 megabytes. For the user, it then looks like a desktop application.
Installation
When installing Blazor, it is important that you select the desired project.
Example
In this case I show how powerful Blazor Server is.
This Razor file is enough to build a fully functional counter.
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
Razor Pages
Tutorial: https://docs.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/?view=aspnetcore-6.0 (opens in a new tab) Documentation: https://docs.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-6.0&tabs=visual-studio (opens in a new tab)
What is Razor Pages?
With the MVC model, you had to take care of a lot of things in different places. With Razor Pages you should be able to create pages more productively
. According to Microsoft, Razor Pages is the newer and simpler model like MVC. Each file represents an endpoint. And the HTML can be output elegantly
using C#.
This project type is particularly recommended for static applications. This is because server-side rendering is extremely fast.
Installation
Here you can already make use of the Razor Pages features after the ASP.NET Core Web App installation.
Example
As you can see from this simple example, a page consists of two files.
The cshtml file represents the page.
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
The data is provided in the cshtml.cs
file.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
In this further, somewhat larger example, you can clearly see how the two files interact.
In the nested cshtml.cs
file, the data is handled and delivered to the page.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class EditModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public EditModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
[BindProperty]
public Movie Movie { get; set; } = default!;
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null || _context.Movie == null)
{
return NotFound();
}
var movie = await _context.Movie.FirstOrDefaultAsync(m => m.ID == id);
if (movie == null)
{
return NotFound();
}
Movie = movie;
return Page();
}
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see https://aka.ms/RazorPagesCRUD.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(Movie).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(Movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
private bool MovieExists(int id)
{
return (_context.Movie?.Any(e => e.ID == id)).GetValueOrDefault();
}
}
}
The cshtml files contain, among other things, ordinary HTML. However, the data from the controller can be used here.
Here you can see again that the different concepts do not differ from each other in all respects.
@page
@model RazorPagesMovie.Pages.Movies.EditModel
@{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Movie.ID" />
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
API
The API model is also worth mentioning at this point.
There is no GUI in such projects. You create an application that returns a json (or other data) in response to requests. In this way, the
data is also well protected.
The purpose of this is that another application, such as a React project, makes use of the API.
You should not create such a project if you want to create an application in a short space of time. Because for a user to be able to operate the app,
it must first be used by a frontend.
(Unless you want the user to send the data in the request body. However, this is not suitable for the DAU (opens in a new tab)).
Conclusion
In my current project, I am working with the MVC model. So far, I have only had positive experiences with it. In my opinion
, MVC makes it possible to work efficiently. In addition, the strict separation keeps everything clean and clear.
However, I have also tried the other models. So far, I can't find anything wrong with them either.
You can't say that one of the models is better than the others. Depending on the project, there is a variant that makes the most sense.
It is therefore helpful if you know the concepts and can differentiate between them.
Note: You can also combine projects if necessary.
Here is an overview of the most important points.
Project type | Advantages | Disadvantages |
---|---|---|
Web Forms | Drag and Drop | No longer modern, outdated tutorials, should no longer be used |
MVC | High speed, GUI and API possible in one project, well-known concept, widely used | Already somewhat older, Blazor Server as a modern alternative |
Blazor Server | Best speed, server-side and client-side rendering, high interactivity for the user | Not optimal for static pages |
Blazor WebAssembly | Offline access after download (approx. 10 MB) | Client-side only, security risks, requires API usage |
Razor Pages | High speed, fast page creation, best choice for static content | Server-side bound |
API | Very fast, easy to implement, high security | No GUI, must be used by other applications, not directly comparable with the other project types |