Introduction
This is Part II of a multi-part article that demonstrates the mapping of C# enum
values to string
values in database tables via EntityFramework Core 2.1 (EF). It addresses the mapping of enum
values in one-to-many and many-to-many relationships with application entities. It does this in the context of an ASP.NET Core Razor Page application.
EF is an Object-Relational Mapper (ORM). In an application such as this sample, there are two "worlds". One is the object world that exists as an object model in C#. The other is the relational world that exists in a relational database, like Microsoft SQL Server. These two worlds are not consistent with each other. The function of an ORM, like EntityFramework
, is the bridge these two worlds and facilitates the transfer of data between them.
Part I: We created initial object model, Entity Framework data context and database and displayed the first Customers Razor Page. This is the Read function of Customer CRUD for all defined Customers.
In Part II, we will complete and test Customer CRUD Razor pages:
- Implement and test the Customer creation Razor Page, Customers\Create.cshtml. This is the
Create
function of Customer
CRUD. - Implement the display of
Customer
details, an implementation of the Read
function for a single Customer
as identified by its CustomerId
property, in the Customers\Details.cshtml Razor Page. - Implement editing of
Customer
properties, the Update
function of Customer
CRUD, in the Customers\Edit.cshtml Razor Page. - Finally, implement the
Delete
function of Customer
CRUD in the Customers\Delete.cshtml Razor Page.
In Part III, we will create Project and ProjectState entities and implement a one-to-many relationship between ProjectState and Projects.
In Part IV, we will add Skill entities (Skill enum, SkillTitle and ProjectSkill) and implement a many-to-many relationship between Projects and Skills.
Using the Code
Complete Customers CRUD
At this point, we have the basic reading of the Customers
table done. Now, we will complete the remaining Customer
CRUD functions.
Customer Creation
The Pages\Customers\Create files handle the creation of Customer
records in the database.
Generated Pages\Customers\Create.cshtml
@page
@model QuantumWeb.Pages.Customers.CreateModel
@{
ViewData["Title"] = "Create";
}
<h2>Create</h2>
<h4>Customer</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Customer.CustomerName" class="control-label"></label>
<input asp-for="Customer.CustomerName" class="form-control" />
<span asp-validation-for="Customer.CustomerName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Customer.CustomerContact" class="control-label"></label>
<input asp-for="Customer.CustomerContact" class="form-control" />
<span asp-validation-for="Customer.CustomerContact" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Customer.CustomerPhone" class="control-label"></label>
<input asp-for="Customer.CustomerPhone" class="form-control" />
<span asp-validation-for="Customer.CustomerPhone" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Customer.CustomerEmail" class="control-label"></label>
<input asp-for="Customer.CustomerEmail" class="form-control" />
<span asp-validation-for="Customer.CustomerEmail" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
This file contains a <form>
element that is used to POST
user input to the server.
Modified Pages\Customers\Create.cshtml.cs
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using QuantumWeb.Data;
using QuantumWeb.Model;
namespace QuantumWeb.Pages.Customers
{
public class CreateModel : PageModel
{
private readonly QuantumDbContext _context;
public CreateModel(QuantumDbContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Customer.Add(Customer);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
One can reach the Customers
/Create
page by clicking the "Create New" link on the Customers
page.
QuantumWeb Application Customers Page: https//localhost: 44306/Customers
Enter the first Customer
's data on the Customer Create page and click "Create".
QuantumWeb Application Customers Page: https//localhost: 44306/Customers/Create
QuantumWeb Application Customers Page: https//localhost: 44306/Customers with 1st Customer
After adding two more Customers
, we display the Customer
page.
QuantumWeb Application Customers Page: https//localhost: 44306/Customers - 3 Customers
We can display the details for the customer
, Polyolefin Processing, Inc,, by clicking its "Details" link. The Customers\Details.cshtml and Customers\Details.cshtml.cs files are listed next.
Display Customer Details
Generated Pages\Customers\Details.cshtml
@page
@model QuantumWeb.Pages.Customers.DetailsModel
@{
ViewData["Title"] = "Details";
}
<h2>Details</h2>
<div>
<h4>Customer</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Customer.CustomerName)
</dt>
<dd>
@Html.DisplayFor(model => model.Customer.CustomerName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Customer.CustomerContact)
</dt>
<dd>
@Html.DisplayFor(model => model.Customer.CustomerContact)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Customer.CustomerPhone)
</dt>
<dd>
@Html.DisplayFor(model => model.Customer.CustomerPhone)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Customer.CustomerEmail)
</dt>
<dd>
@Html.DisplayFor(model => model.Customer.CustomerEmail)
</dd>
</dl>
</div>
<div>
<a asp-page="./Edit" asp-route-id="@Model.Customer.CustomerId">Edit</a> |
<a asp-page="./Index">Back to List</a>
</div>
Modified Pages\Customers\Details.cshtml.cs
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using QuantumWeb.Data;
using QuantumWeb.Model;
namespace QuantumWeb.Pages.Customers
{
public class DetailsModel : PageModel
{
private readonly QuantumDbContext _context;
public DetailsModel(QuantumDbContext context)
{
_context = context;
}
public Customer Customer { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Customer = await _context.Customer.FirstOrDefaultAsync(m => m.CustomerId == id);
if (Customer == null)
{
return NotFound();
}
return Page();
}
}
}
QuantumWeb Application Customer Details Page: https//localhost: 44306/Customers/Details?id=2
QuantumWeb Application Customers Page: https//localhost: 44306/Customers - 3 Customers
We can edit the record for the customer
, Pascagoula Petrochemicals, by clicking its "Edit" link. The Customers\Edit.cshtml and Customers\Edit.cshtml.cs files are listed next.
Edit Customer Information
Generated Pages\Customers\Edit.cshtml
@page
@model QuantumWeb.Pages.Customers.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Customer</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="Customer.CustomerId" />
<div class="form-group">
<label asp-for="Customer.CustomerName" class="control-label"></label>
<input asp-for="Customer.CustomerName" class="form-control" />
<span asp-validation-for="Customer.CustomerName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Customer.CustomerContact" class="control-label"></label>
<input asp-for="Customer.CustomerContact" class="form-control" />
<span asp-validation-for="Customer.CustomerContact" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Customer.CustomerPhone" class="control-label"></label>
<input asp-for="Customer.CustomerPhone" class="form-control" />
<span asp-validation-for="Customer.CustomerPhone" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Customer.CustomerEmail" class="control-label"></label>
<input asp-for="Customer.CustomerEmail" class="form-control" />
<span asp-validation-for="Customer.CustomerEmail" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Modified Pages\Customers\Edit.cshtml.cs
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using QuantumWeb.Data;
using QuantumWeb.Model;
namespace QuantumWeb.Pages.Customers
{
public class EditModel : PageModel
{
private readonly QuantumDbContext _context;
public EditModel(QuantumDbContext context)
{
_context = context;
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Customer = await _context.Customer.FirstOrDefaultAsync(m => m.CustomerId == id);
if (Customer == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(Customer).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!CustomerExists(Customer.CustomerId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
private bool CustomerExists(int id)
{
return _context.Customer.Any(e => e.CustomerId == id);
}
}
}
QuantumWeb Application Customer Edit Page: https//localhost: 44306/Customers/Edit?id=3
We change values for the selected Customer
and save the changes.
QuantumWeb Application Customers Page: https//localhost: 44306/Customers - Changed Customer
We see the edited values. Now, we delete a Customer
by clicking its "Delete" link. The Customers\Delete.cshtml and Customers\Delete.cshtml.cs files are listed next.
Delete Customer Record
Generated Pages\Customers\Delete.cshtml
@page
@model QuantumWeb.Pages.Customers.DeleteModel
@{
ViewData["Title"] = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>Customer</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Customer.CustomerName)
</dt>
<dd>
@Html.DisplayFor(model => model.Customer.CustomerName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Customer.CustomerContact)
</dt>
<dd>
@Html.DisplayFor(model => model.Customer.CustomerContact)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Customer.CustomerPhone)
</dt>
<dd>
@Html.DisplayFor(model => model.Customer.CustomerPhone)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Customer.CustomerEmail)
</dt>
<dd>
@Html.DisplayFor(model => model.Customer.CustomerEmail)
</dd>
</dl>
<form method="post">
<input type="hidden" asp-for="Customer.CustomerId" />
<input type="submit" value="Delete" class="btn btn-default" /> |
<a asp-page="./Index">Back to List</a>
</form>
</div>
Modified Pages\Customers\Delete.cshtml.cs:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using QuantumWeb.Data;
using QuantumWeb.Model;
namespace QuantumWeb.Pages.Customers
{
public class DeleteModel : PageModel
{
private readonly QuantumDbContext _context;
public DeleteModel(QuantumDbContext context)
{
_context = context;
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Customer = await _context.Customer.FirstOrDefaultAsync(m => m.CustomerId == id);
if (Customer == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Customer = await _context.Customer.FindAsync(id);
if (Customer != null)
{
_context.Customer.Remove(Customer);
await _context.SaveChangesAsync();
}
return RedirectToPage("./Index");
}
}
}
QuantumWeb Application Customer Delete Page: https//localhost: 44306/Customers/Delete?id=3
We display the details for the customer, Pascagoula Petrochemicals, Ltd, with the option to delete it by clicking the "Delete" button.
QuantumWeb Application Customers Page: https//localhost: 44306/Customers - 2 Customers
Summary
We have implemented the Customer
CRUD ASP.NET Razor Pages.
Points of Interest
In Part III of this article, we will add definitions of Project
and ProjectState
entities (Project
, ProjectState
and ProjectStateDescription
) and implement a one-to-many relationship between ProjectState
s and Project
s.