(C# ASP.NET Core) Getting Started with Database INSERT of Form data

A form of only one input textbox is POSTed and the data is inserted into a sqlite database. This is a six step walkthrough that starts from creating a model, followed by a DAL based on the DbContext class. We also explain how an application is configured for dependency injection of the DbContext, and also, how the DbContext is extracted from the constructor of a PageModel class, and ultimately used to run a database query.
(Rev. 19-Mar-2024)

Categories | About |     |  

Parveen,

Objective of this Tutorial

We shall have a simple form of one textbox for inserting a record into a database.

The backend database will be Sqlite.

The saved data is not displayed in this tutorial. We reserve that for some future tutorial.

Video Explanation with a Working Example

Please watch the following youtube video:

Step 1 of 6: Decide your Database and add its Nuget Package

We shall use sqlite database, but you can use any. Except the connection string everything else remains the same.

Add its nuget package as explained in the previous tutorial - "Various Database Options and the initial Setup"

Step 2 of 6: Decide on the Model

A model maps to a table in your database.

Create a folder called "Models" and add a class called Product to it.

A model must contain a primary key, and, therefore, a property called ID or a property suffixed with ID or a property marked with the attribute [Key] has to be added to a model class.

using Microsoft.EntityFrameworkCore;

using System;

using System.ComponentModel.DataAnnotations;

using System.ComponentModel.DataAnnotations.Schema;

using System.Diagnostics.CodeAnalysis;

public class Product
{

  // auto-increment Primary ID key 
  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public int ID { get; set; }

  // just one property 
  public String Name { get; set; }
}

Step 3 of 6: Write your DAL based on DbContext
(see the linked video for details)

Data access layer [DAL] is written by inheriting a class from the readymade DbContext class.

DbContext represents your entire database - there is one DbContext for a whole physical database.

The class must contain a default constructor with DbContextOptions.

You must override the OnModelCreating method to specify foreign key constraints, indexes, and the names of database tables for each model. The names of the tables are useful if you have to run direct SQL queries against your database.

The last important thing is the DbSet collection property corresponding to each model (i.e., table) in the database. The name of this property must be pluralized - like for example, Products. A DbSet represents a [virtual] collection of the records of your table. Records can be added and queried by using various methods like Insert, Add, Update, etc., that are available on dotnet collections. A modified record, for example, is internally marked dirty, and, on Save(), the EF framework runs an UPDATE SQL query on the physical database.

Add the following ProductContext class. This class can be added in the same file as one of the models, or a different file depending on the complexity of your project.

using Microsoft.EntityFrameworkCore;

using System;

using System.ComponentModel.DataAnnotations;

using System.ComponentModel.DataAnnotations.Schema;

using System.Diagnostics.CodeAnalysis;

// dbcontext DAL - THERE IS ONE DbContext per database 
public class ProductContext : DbContext
{

  public ProductContext(DbContextOptions options) : base(options)
  {

    // EnsureCreated is meant for testing or creating 
    // a blank database. this code should be avoided 
    // at this place. use some alternate program to 
    // create/migrate your database. this code has been 
    // used here only for tutorial purposes 
    Database.EnsureCreated();

  }

  // this function is used to specify FK relations, Indexes, 
  // and [optionally] the name of your database tables 
  // corresponding to each model 
  protected override void OnModelCreating(ModelBuilder modelBuilder)
  {

    base.OnModelCreating(modelBuilder);

    // name of the table in your database 
    modelBuilder.Entity<Product>().ToTable("product");

  }

  // MUST be PLURAL 
  public DbSet<Product> Products { get; set; }

  // more DbSet are added here - one for 
  // each model (i.e., table) 
}

Step 4 of 6: Dependency Injection of the ProductContext

An instance of the ProductContext is required for executing database queries.

The best way is to obtain it is through Dependency Injection. The ASPNET framework can make it available to us through the constructor of a class whenever we need it (see Step 5 below).

Add a line to the ConfigureServices method of the Startup class and specify your connection string also:

using DBaseCon;

using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Hosting;

using Microsoft.EntityFrameworkCore;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.Extensions.Hosting;

namespace Modular
{

  public class Startup
  {

    public void ConfigureServices(IServiceCollection services)
    {

      // make an arrangement for DependencyInjection 
      // of ProductContext instance. the database is 
      // created in the root directory of your project 
      // alternately create a folder, say, DBase and then 
      // specify the path as DBase/mydb.db 
      services.AddDbContext<ProductContext>(
      opt => opt.UseSqlite("Data Source=mydb.db"));

      // add support for razor pages 
      services.AddRazorPages();

    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {

      if (env.IsDevelopment())
      {

        app.UseDeveloperExceptionPage();

      }

      app.UseRouting();

      app.UseEndpoints(endpoints =>
      {

        // add razor pages as the end-points 
        endpoints.MapRazorPages();

      });

    }

  }

}

Step 5 of 6: Grabbing the ProductContext
(see the linked video for details)

ProductContext can be obtained in the constructor of your PageModel class.

A 2-way property binding is required for your data-entry form. This property contains the form data when a user fills the form and submits it.

A form submit is handled through the OnPost method of the PageModel class.

In the OnPost method, save the record to the database as shown below. Since the record is a new record, an INSERT query will be run by the EF Core.

Complete the backing class file Index.cshtml.cs thus:

using DBaseCon;

using Microsoft.AspNetCore.Mvc;

using Microsoft.AspNetCore.Mvc.RazorPages;

namespace Modular.Pages
{

  public class IndexModel : PageModel
  {

    private readonly ProductContext _ctx;

    // dependency injection of the ProductContext 
    public IndexModel(ProductContext ctx)
    {

      _ctx = ctx;

    }

    // 2-way binding 
    [BindProperty]
    public Product Prod { get; set; }

    // save the posted form data 
    // in the OnPost handler 
    // NOTE: strictly speaking, this method 
    // must be asynchronous. we shall make 
    // that correction in later tutorials 
    public ActionResult OnPost()
    {

      _ctx.Products.Add(Prod);

      _ctx.SaveChanges();

      // redirect and show the 
      // form again 
      return RedirectToPage();

    }

  }

}

Step 6 of 6: Complete the Data Entry Form
(see the linked video for details)

Write this into the Index.cshtml razor page file:


@page

@model Modular.Pages.IndexModel

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<form method="post">

  Name: <input asp-for="Prod.Name"  /> 
  
  <input type="submit" />

</form>


This Blog Post/Article "(C# ASP.NET Core) Getting Started with Database INSERT of Form data" by Parveen is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.