Click here to Skip to main content
14,546,341 members

ASP.NET Core Razor Pages Using EntityFramework Core with Enums as Strings - Part II

Rate this:
5.00 (3 votes)
Please Sign up or sign in to vote.
5.00 (3 votes)
2 Dec 2018CPOL
Complete Initial CRUD Pages

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;
        } // end public CreateModel(QuantumDbContext context)

        public IActionResult OnGet()
        {
            return Page();
        } // end public IActionResult OnGet()

        [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");
        } // end public async Task<IActionResult> OnPostAsync()

    } // end public class CreateModel : PageModel

} // end namespace QuantumWeb.Pages.Customers

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

Image 1

Enter the first Customer's data on the Customer Create page and click "Create".

QuantumWeb Application Customers Page: https//localhost: 44306/Customers/Create

Image 2

QuantumWeb Application Customers Page: https//localhost: 44306/Customers with 1st Customer

Image 3

After adding two more Customers, we display the Customer page.

QuantumWeb Application Customers Page: https//localhost: 44306/Customers - 3 Customers

Image 4

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;
        } // end public DetailsModel(QuantumDbContext context)

        public Customer Customer { get; set; }

        public async Task<IActionResult> OnGetAsync(int? id)
        {
            if (id == null)
            {
                return NotFound();
            } // end if (id == null)

            Customer = await _context.Customer.FirstOrDefaultAsync(m => m.CustomerId == id);

            if (Customer == null)
            {
                return NotFound();
            } // endif (Customer == null)
            return Page();
        } // end public async Task<IActionResult> OnGetAsync(int? id)

    } // end public class DetailsModel : PageModel

} // end namespace QuantumWeb.Pages.Customers
QuantumWeb Application Customer Details Page: https//localhost: 44306/Customers/Details?id=2

Image 5

QuantumWeb Application Customers Page: https//localhost: 44306/Customers - 3 Customers

Image 6

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;
        } // end public EditModel(QuantumDbContext context)

        [BindProperty]
        public Customer Customer { get; set; }

        public async Task<IActionResult> OnGetAsync(int? id)
        {
            if (id == null)
            {
                return NotFound();
            } // endif (id == null)

            Customer = await _context.Customer.FirstOrDefaultAsync(m => m.CustomerId == id);

            if (Customer == null)
            {
                return NotFound();
            } // endif (Customer == null)
            return Page();
        } // end public async Task<IActionResult> OnGetAsync(int? id)

        public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            } // endif (!ModelState.IsValid)

            _context.Attach(Customer).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            } // end try
            catch (DbUpdateConcurrencyException)
            {
                if (!CustomerExists(Customer.CustomerId))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                } // endif (!CustomerExists(Customer.CustomerId))
            } // end catch (DbUpdateConcurrencyException)

            return RedirectToPage("./Index");
        } // end public async Task<IActionResult> OnPostAsync()

        private bool CustomerExists(int id)
        {
            return _context.Customer.Any(e => e.CustomerId == id);
        } // end private bool CustomerExists(int id)

    } // end public class EditModel : PageModel

} // end namespace QuantumWeb.Pages.Customers
QuantumWeb Application Customer Edit Page: https//localhost: 44306/Customers/Edit?id=3

Image 7

We change values for the selected Customer and save the changes.

QuantumWeb Application Customers Page: https//localhost: 44306/Customers - Changed Customer

Image 8

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;
        } // end public DeleteModel(QuantumDbContext context)

        [BindProperty]
        public Customer Customer { get; set; }

        public async Task<IActionResult> OnGetAsync(int? id)
        {
            if (id == null)
            {
                return NotFound();
            } // endif (id == null)

            Customer = await _context.Customer.FirstOrDefaultAsync(m => m.CustomerId == id);

            if (Customer == null)
            {
                return NotFound();
            } // endif (Customer == null)
            return Page();
        } // end public async Task<IActionResult> OnGetAsync(int? id)

        public async Task<IActionResult> OnPostAsync(int? id)
        {
            if (id == null)
            {
                return NotFound();
            } // endif (id == null)

            Customer = await _context.Customer.FindAsync(id);

            if (Customer != null)
            {
                _context.Customer.Remove(Customer);
                await _context.SaveChangesAsync();
            } // endif (Customer != null)

            return RedirectToPage("./Index");
        } // end public async Task<IActionResult> OnPostAsync(int? id)

    } // end public class DeleteModel : PageModel

} // end namespace QuantumWeb.Pages.Customers
QuantumWeb Application Customer Delete Page: https//localhost: 44306/Customers/Delete?id=3

Image 9

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

Image 10

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 ProjectStates and Projects.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Leonard E. James
President Lionhart Technologies, LLC
United States United States
Technical professional with experience as Software Architect, IT Consultant, Developer, Engineer and Research Chemist. Current areas of emphasis are .NET, Entity Framework, application design and analysis.

Comments and Discussions

 
-- There are no messages in this forum --
Article
Posted 28 Oct 2018

Stats

6.6K views
132 downloads
6 bookmarked