C# – ASP.NET Core MVC Application with Basic Database Access using Entity Framework – Video
The title somehow looks like random words, picked from a hat at one of those college games we are not supposed to talk about. Anyway, at the second reading it hopefully becomes a bit clearer. And it is simply the “magic” of creating 2 C# classes in visual studio and transferring them to tables in a database with the magic of Entity Framework. Then, with ASP, being able to access the database with the 2 tables and making simple CRUD (Create, Read, Update, Delete) actions. This is how the R in CRUD looks like:

As mentioned, there are 2 main classes in the application – Blog.cs and Post.cs and these have a relation 1-to-many between each other:

As far as the code is mainly generated from the scaffold features of Visual Studio, I will show only the PostController.cs and the \Posts\Details.cshtml here. The rest is in GitHub and in the video.
PostController.cs
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using EFGetStarted.Models;
namespace EFGetStarted.Controllers
{
public class PostsController : Controller
{
private readonly BloggingContext _context;
public PostsController(BloggingContext context)
{
_context = context;
}
// GET: Posts
public async Task Index()
{
var bloggingContext = _context.Posts.Include(p => p.Blog);
return View(await bloggingContext.ToListAsync());
}
// GET: Posts/Details/5
public async Task Details(int? id)
{
if (id == null)
{
return NotFound();
}
var post = await _context.Posts
.Include(p => p.Blog)
.FirstOrDefaultAsync(m => m.PostId == id);
if (post == null)
{
return NotFound();
}
return View(post);
}
// GET: Posts/Create
public IActionResult Create()
{
ViewData["BlogId"] = new SelectList(_context.Blogs, "BlogId", "BlogId");
return View();
}
// POST: Posts/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task Create([Bind("PostId,Title,Content,BlogId")] Post post)
{
if (ModelState.IsValid)
{
_context.Add(post);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["BlogId"] = new SelectList(_context.Blogs, "BlogId", "BlogId", post.BlogId);
return View(post);
}
// GET: Posts/Edit/5
public async Task Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var post = await _context.Posts.FindAsync(id);
if (post == null)
{
return NotFound();
}
ViewData["BlogId"] = new SelectList(_context.Blogs, "BlogId", "BlogId", post.BlogId);
return View(post);
}
// POST: Posts/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task Edit(int id, [Bind("PostId,Title,Content,BlogId")] Post post)
{
if (id != post.PostId)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(post);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!PostExists(post.PostId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
ViewData["BlogId"] = new SelectList(_context.Blogs, "BlogId", "BlogId", post.BlogId);
return View(post);
}
// GET: Posts/Delete/5
public async Task Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var post = await _context.Posts
.Include(p => p.Blog)
.FirstOrDefaultAsync(m => m.PostId == id);
if (post == null)
{
return NotFound();
}
return View(post);
}
// POST: Posts/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task DeleteConfirmed(int id)
{
var post = await _context.Posts.FindAsync(id);
_context.Posts.Remove(post);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool PostExists(int id)
{
return _context.Posts.Any(e => e.PostId == id);
}
}
}
\Posts\Details.cshtml
@model EFGetStarted.Models.Post
@{
ViewData["Title"] = "Details";
}
<h2>Details</h2>
<div>
<h4>Post</h4>
<hr>
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Title)
</dt>
<dd>
@Html.DisplayFor(model => model.Title)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Content)
</dt>
<dd>
@Html.DisplayFor(model => model.Content)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Blog)
</dt>
<dd>
@Html.DisplayFor(model => model.Blog.BlogId)
</dd>
</dl>
</div>
<div>
<a asp-action="Edit" asp-route-id="@Model.PostId">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>
The video:
The GitHub code:
https://github.com/Vitosh/ASP/tree/master/EFGetStarted
The Original Microsoft.com tutorial:
https://docs.microsoft.com/en-us/ef/core/get-started/aspnetcore/new-db?tabs=visual-studio