Step by step guide on how to create an  Asp.Net Core MVC CRUD, Ef Core code first approach
Tags: dotnet, beginners, sql, tutorial
Published: 2021-01-12 06:16:35

In this article we will be exploring how to create an  Asp.Net Core MVC CRUD, Ef Core code first approach you can watch the full tutorial on Youtube as well 

{% youtube 015pIQFkH78 %}

Source code: https://github.com/mohamadlawand087/v4-Phonebook

The 3 things that we will need before we start:

- Visual Studio code (https://code.visualstudio.com)
- Dotnet core SDK ([https://dotnet.microsoft.com/download](https://dotnet.microsoft.com/download))
- Download sqllite browser [https://sqlitebrowser.org/dl/](https://sqlitebrowser.org/dl/)

For this sample application we will be using SQLite as our local database. After installing all of  requirements, we need to make sure that the dotnet SDK has been installed successfully, we need to open the terminal and check if the dotnet SDK is installed successfully by  checking the dotnet version.

Open the terminal type the command below

```csharp
dotnet --version
```
Now we need to install the entity framework tool

```csharp
dotnet tool install --global dotnet-ef
```

Now we need to create an asp.net core application using the following command

```bash
dotnet new mvc -n "Phonebook" -lang "C#" -au none
```

Now we need to add the required packages to utilise SQLLite and Entity Framework Core

```bash
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet add package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
```

Once we add the packages we need to update the appsettings.json to include the connection string to our database

```jsx
"ConnectionStrings": {
    "DefaultConnection": "DataSource=app.db;Cache=Shared"
  }
```

We open visual studio code, we need to open the terminal from within visual studio code.You can go to Views ⇒ Terminal. Now we need to make sure that the application is building by running the code below

```bash
dotnet build
dotnet run
```

Once we make sure that the application is running we will start by creating our ApplicationDbContext. We need to create a Data folder in he root directory, and then will create the ApplicationDbContext class

```csharp
using Microsoft.EntityFrameworkCore;

namespace Phonebook.Data
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
    }
}
```

Once we add our ApplicationDbContext we need to update the startup class to utilise the DbContext

```csharp
services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlite(
                    Configuration.GetConnectionString("DefaultConnection")));
            services.AddDatabaseDeveloperPageExceptionFilter();
```

Once we have add the DbContext middleware we need to add the initial migration to create the database.

```bash
dotnet ef migrations add "Initial Migrations"
dotnet ef database update
```

lets now check our solution and see if we have the database file create, we can now see the database is there.

So our next step is to create our Model, we will call it Contact. 

Inside the model folder create a new C# class and call it Contact, inside the Contact class we will define 5 properties "Id", "First Name", "Last Name", "Email", "Mobile".

```csharp
public class Contact
{
	  public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string Mobile { get; set; }
}
```

Now we need to add our Model to the application DbContext by adding the code below

```csharp
public class ApplicationDbContext : DbContext
{
		// The DbSet property will tell EF Core tha we have a table that needs to be created
    public virtual DbSet<Contact> Contacts { get; set; }

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
    
		// On model creating function will provide us with the ability to manage the tables properties
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}
```

Once we update the ApplicationDbContext we need to create a new migration script to prepare the EF Core to update our database

```bash
dotnet ef migrations add "Adding the Contact table"
dotnet ef database update 
```

After the database update is completed, we can check our sqlite db with the SQLite browser, we can see that the table has been created for us.

Now we need to create the controller and create the actions. Right click on the controller folder and add a new class calling it ContactsController and we need to inherit from the controller class

```csharp
public class ContactsController : Controller
{
    
}
```

We need to create and initiate the ApplicationDbContext inside our new Contacts controller and create the action index, and get all of the contacts from the database

```csharp
public class ContactsController : Controller
{
    private ApplicationDbContext _context;

    public ContactsController(ApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<IActionResult> Index()
    {
        var contacts = await _context.Contacts.ToListAsync();
        return View(contacts);
    }
}
```

Now we need to create the view folder for the controller, under the views folder we need to create a folder called Contacts.

once we create the folder we need to create a view for the index, within the index we need to create a table which will list all of the contacts that we have.

```html
@model List<Phonebook.Models.Contact>

<div class="row">
    <div class="col-md-12">
        <a asp-action="Create" asp-controller="Contacts" class="btn btn-success">Create</a>
    </div>
</div>
<div class="row">
    <div class="col-md-12">
        <table class="table">
            <thead>
                <tr>
                    <td>First Name</td>
                    <td>Last Name</td>
                    <td>Email</td>
                    <td>Mobile</td>
                    <td>Manage</td>
                </tr>
            </thead>
            <tbody>
            @foreach (var item in Model)
            {
                <tr>
                    <td>@item.FirstName</td>
                    <td>@item.LastName</td>
                    <td>@item.Email</td>
                    <td>@item.Mobile</td>
                    <td>
                        <a asp-action="Edit" asp-controller="Contacts" asp-route-id="@item.Id">
                            Edit
                        </a>
                        <a asp-action="Delete" asp-controller="Contacts" asp-route-id="@item.Id">
                            Delete
                        </a>
                    </td>
                </tr>
            }
            </tbody>
        </table>
    </div>
</div>
```

Once we create it we need to build and run the application to make sure everything is running as it should be

```bash
dotnet build
dotnet run

```

When we go to the ContactsController we can see there is nothing in our table since we didnt add any record yet which is the correct behaviour, now lets start creating the Create action to add information to our database. 

```csharp
[HttpGet]
public IActionResult Create()
{
    return View();
}

[HttpPost]
public async Task<IActionResult> Create(Contact contact)
{
    // validate that our model meets the requirement
    if (ModelState.IsValid)
    {
        try
        {
            // update the ef core context in memory 
            _context.Add(contact);

            // sync the changes of ef code in memory with the database
            await _context.SaveChangesAsync();

            return RedirectToAction("Index");
        }
        catch(Exception ex)
        {
            ModelState.AddModelError(string.Empty, $"Something went wrong {ex.Message}");
        }
    }

    ModelState.AddModelError(string.Empty, $"Something went wrong, invalid model");

    // We return the object back to view
    return View(contact);
}
```

```html
@model Phonebook.Models.Contact

<form asp-action="Create" asp-area="Contacts" method="post">
    <div class="row">
        <div class="col-lg-12">
            <div class="form-group">
                <label>First Name:</label>
                <input asp-for="FirstName" type="text" class="form-control required" placeholder="Enter first name" tabindex="1">
            </div>
             <div class="form-group">
                <label>Last Name:</label>
                <input asp-for="LastName" type="text" class="form-control required" placeholder="Enter last name" tabindex="2">
            </div>
             <div class="form-group">
                <label>Email:</label>
                <input asp-for="Email" type="text" class="form-control required" placeholder="Enter email" tabindex="3">
            </div>
             <div class="form-group">
                <label>Mobile:</label>
                <input asp-for="Mobile" type="text" class="form-control required" placeholder="Enter mobile" tabindex="4">
            </div>
            <div class="form-group">
                <div asp-validation-summary="All" class="text-danger"></div>
            </div>
            <div class="card-footer">
                <center>
                    <button type="submit" class="btn btn-primary">Create Contact</button>
                    <a asp-action="Index" asp-controller="Contacts" class="btn btn-secondary">Cancel</a>
                </center>
            </div>
        </div>
    </div>
</form>
```

Once we create it we need to build and run the application to make sure everything is running as it should be

```bash
dotnet build
dotnet run
```

lets navigate to the create page and add some records we can now see the data is being populated as it should from the database 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0e10m9w7f6yylnp23y70.png)

Now we need to add the edit functionality so we can update our contacts, in order for us to do that we need to add the Edit action as well the Edit View.

```csharp
[HttpGet]
public async Task<IActionResult> Edit(int id)
{
    var exist = await _context.Contacts.Where(x => x.Id == id).FirstOrDefaultAsync();

    return View(exist);
}

[HttpPost]
public async Task<IActionResult> Edit(Contact contact)
{
    // validate that our model meets the requirement
    if (ModelState.IsValid)
    {
        try
        {
            // Check if the contact exist based on the id
            var exist = _context.Contacts.Where(x => x.Id == contact.Id).FirstOrDefault();

            // if the contact is not null we update the information
            if(exist != null)
            {
                exist.FirstName = contact.FirstName;
                exist.LastName = contact.LastName;
                exist.Mobile = contact.Mobile;
                exist.Email = contact.Email;

                // we save the changes into the db
                await _context.SaveChangesAsync();

                return RedirectToAction("Index");
            }
        }
        catch(Exception ex)
        {
            ModelState.AddModelError(string.Empty, $"Something went wrong {ex.Message}");
        }
    }

    ModelState.AddModelError(string.Empty, $"Something went wrong, invalid model");

    return View(contact);
}
```

```html
@model Phonebook.Models.Contact

<form asp-action="Edit" asp-area="Contacts" method="post">
    <input type="hidden" asp-for="Id" />
    <div class="row">
        <div class="col-lg-12">
            <div class="form-group">
                <label>First Name:</label>
                <input asp-for="FirstName" type="text" class="form-control required" placeholder="Enter first name" tabindex="1">
            </div>
             <div class="form-group">
                <label>Last Name:</label>
                <input asp-for="LastName" type="text" class="form-control required" placeholder="Enter last name" tabindex="2">
            </div>
             <div class="form-group">
                <label>Email:</label>
                <input asp-for="Email" type="text" class="form-control required" placeholder="Enter email" tabindex="3">
            </div>
             <div class="form-group">
                <label>Mobile:</label>
                <input asp-for="Mobile" type="text" class="form-control required" placeholder="Enter mobile" tabindex="4">
            </div>
            <div class="form-group">
                <div asp-validation-summary="All" class="text-danger"></div>
            </div>
            <div class="card-footer">
                <center>
                    <button type="submit" class="btn btn-warning">Update Contact</button>
                    <a asp-action="Index" asp-controller="Contacts" class="btn btn-secondary">Cancel</a>
                </center>
            </div>
        </div>
    </div>
</form>
```

lets run the application now and test the functionality

```bash
dotnet build
dotnet run
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/73q4iodhfqd6qe6ipggv.png)

And finally we need to add the Delete action and view to be able to remove contacts

```csharp
[HttpGet]
public async Task<IActionResult> Delete(int id)
{
    var exist = await _context.Contacts.Where(x => x.Id == id).FirstOrDefaultAsync();

    return View(exist);
}

[HttpPost]
public async Task<IActionResult> Delete(Contact contact)
{
    if (ModelState.IsValid)
    {
        try
        {
            var exist = _context.Contacts.Where(x => x.Id == contact.Id).FirstOrDefault();

            if(exist != null)
            {
                _context.Remove(exist);
                await _context.SaveChangesAsync();

                return RedirectToAction("Index");
            } 
        }
        catch(Exception ex)
        {
            ModelState.AddModelError(string.Empty, $"Something went wrong {ex.Message}");
        }
    }

    ModelState.AddModelError(string.Empty, $"Something went wrong, invalid model");

    return View();
}
```

```html
@model Phonebook.Models.Contact

<form asp-action="Delete" asp-area="Contacts" method="post">
    <input type="hidden" asp-for="Id" />
    <div class="row">
        <div class="col-lg-12">
            <div class="form-group">
                <label>First Name:</label>
                <input asp-for="FirstName" type="text" disabled class="form-control required" placeholder="Enter first name" tabindex="1">
            </div>
             <div class="form-group">
                <label>Last Name:</label>
                <input asp-for="LastName" type="text" disabled class="form-control required" placeholder="Enter last name" tabindex="2">
            </div>
             <div class="form-group">
                <label>Email:</label>
                <input asp-for="Email" type="text" disabled class="form-control required" placeholder="Enter email" tabindex="3">
            </div>
             <div class="form-group">
                <label>Mobile:</label>
                <input asp-for="Mobile" type="text" disabled class="form-control required" placeholder="Enter mobile" tabindex="4">
            </div>
            <div class="form-group">
                <div asp-validation-summary="All" class="text-danger"></div>
            </div>
            <div class="card-footer">
                <center>
                    <button type="submit" class="btn btn-danger">Delete Contact</button>
                    <a asp-action="Index" asp-controller="Contacts" class="btn btn-secondary">Cancel</a>
                </center>
            </div>
        </div>
    </div>
</form>
```

now lets run the application now and test the functionality

```bash
dotnet build
dotnet run
```

the last thing we need to do is to add a link to the contacts page in the menu, to do that we need to go to Views ⇒ Shared ⇒ _Layout.cshtml and add the code below

```html
<li class="nav-item">
    <a class="nav-link text-dark" asp-area="" asp-controller="Contacts" asp-action="Index">Contacts</a>
</li>
```