In this tutorial, we will learn a clean and simple way to implement Razor Page CRUD in ASP.NET Core with jQuery AJAX and Bootstrap Modal. The ultimate aim is to build an Entity Management Set of Operations (CRUD) that doesn’t reload pages. We will be achieving this with the help of ASP.NET Core Razor Page, Razor Partial View, JQuery AJAX calls so that you would never have to see your page reload again but everything would just work flawlessly. You can find the complete source code here.
So everything started when I was building the ASP.NET Core Hero - Boilerplate Template. My requirement was quite simple. In the UI Layer, which is ASP.NET Core Razor Pages, I wanted to implement CRUD with the User Experience of a SPA. Meaning, never reload the page but load partial views and modals, you get the point, yeah? Rich User Experience and Blazing Fast Speeds were what I had in mind. But guess what, there was absolutely no other tutorials or references that matched to what I actually wanted. And I ended up researching over it for a couple of days and finally got it to work. So, I decided to document it for others to refer to.
PRO TIP - This is an in-depth article with steps that can get you started from scratch to a complete application which covers many related concepts. Do not forget to bookmark this page for future reference.
Scope
These are the things we will be implementing in our CRUD Application. Note that this will be a Customer Management Application.
- Data Annotations for Validations
- jQuery Validations and Unobstructive Validations - Client Side Validation
- Bootstrap Modals
- Dynamic Loading of Partial Views via AJAX Calls
- Repository Pattern with Unit of Work
- Onion Architecture Solution
- jQuery Datatables
The Architecture
To Keep things Simple and Clean we will be using Onion Architecture with Inverted Dependencies. We will have 3 Layers out of which the Primary one is an ASP.NET Core Web Application with Razor Pages and the other two are the Core and Infrastructure Layer. Core Layer will have the Interfaces and Entities while the Infrastructure Layer will have Entity Framework Core, Repository and Unit Of Work Implementations. At the Web Project we will use jQuery Ajax and Partials Views along with jQuery Datatable to build a super cool CRUD Application. Let’s get started!
If you are interested to read about Onion Architecture in depth, please refer to this article - Onion Architecture In ASP.NET Core With CQRS – Detailed . Also, there is a full-fledged WebAPI Clean Architecture template with which you can install and build API projects in no time (Open Source). Get it here.
Getting Started with Razor Page CRUD in ASP.NET Core
Let’s create the required projects first. I am creating the Web Project first.
Setting up the Projects
After that I am adding in the Core and Infrastructure projects to the same solution. Note that these are .NET Core 3.1 Library Projects.
Setting up the Core Layer
Let’s add the Entity and Interfaces as required in the Core Project.
Add a new Folder in the Core Project and name it Entities. Here let’s add the Customer Entity.
With that done, let’s start adding the Interfaces. Create a new Folder in the Core Project and Name it Interfaces. Since we will be following Repository Pattern, add a IGenericRepositoryAsync Interface.
To learn more about Repository Pattern with Unit Of Work, refer here - Dapper in ASP.NET Core with Repository Pattern
Okay, so we have a generic repository interface. Now to use this generic interface for a specific entity like customer along with extra methods, let’s add another interface and name it ICustomerRepositoryAsync.
Finally, add the Unit of Work Interface.
That’s nearly everything you need to add in the Core Layer. Let’s go to the Infrastructure layer.
Setting up the Infrastructure Layer
Install the required packages on the Infrastructure layer.
Now that you have Entity Framework Core installed at the Infrastructure Layer, let’s add the ApplicationDbContext in-order to access the database. (We will be setting the connection string to the database later in this article at the Web Layer.)
Create a new Folder in the Infrastructure Layer and name it Data. Here add a new Class and name it ApplicationDbContext.cs
Remember we created a bunch of Interfaces back in the Core Layer? The Infrastructure Layer is where you would want to implement those interfaces. This is the core concept of Onion Architecture. We call it Inversion of Dependency. In this way, the Application no longer depends on the Repository / Data Layers. Rather the dependency is inverted. Pretty cool, yeah?
Add a new folder in the Infrastructure layer and name it Repositories. Here add a new class, GenericRepositoryAsync.cs
As you can see from the above , almost all the CRUD operations ever needed for any entity is covered. T could be any class and you already have an entire class that could Perform Create, Read, Update and Delete Operations on the T Entity. But also see that we are not saving anything directly to the database via the Repository Implementation. Rather we will have a seperate class that is responsible for Commiting changes to the database. You should have heard about Unit Of Work, yeah?
Create another new class and name it UnitOfWork.cs in the Infrastructure layer.
Finally add the last implementation that is going to be responsible for performing CRUD operations specific to Customer Entity.
Setting up the ASP.NET Core Project
So, by now we already have all the CRUD Operations figured out at the Repository level . The only task ahead is to make the UI/UX cool and also other minor stuff. Let’s first install the packages required and add the migrations.
With that done, open up the Startup.cs. Here we will have to add the services / dependencies to our ASP.NET Core Container. Navigate to the ConfigureServices method and add in the following. Note that you would have to fix the reference warnings that may occur.
We have registered ApplicationDbContext and other Repositories to the service container. But we are missing the most vital part, the connection string. For this, open up your appsettings.json and add in the following with your own connection string details.
Note that you will have to add the references as you require to and from the 3 Projects. But always remember that with Onion Architecture, the Core Layer is always at the center of the design. So, the Core layer will never depend on any other Layer.
Let’s add our migrations and update the database with the Customer table. Open up Package manage console and run the following command. Note that you have to set the Web Project as the default project and the Infrastructure project as the default project in the package manager tab.
You will probably receive an OK message from Visual Studio. After that, let’s check our database. You can see that the customer table as well as the entire database is created for you.
We essentially have everything figured out for the CRUD operations. Let’s work on the UI now. Luckily we chose Razor pages, which is blazing fast. But, to provide a better User Experience, we need to use some client-side technologies as well such as jQuery Datatables, AJAX calls, and so on. Let’s get started.
By default, every time you create a new ASP.NET Core project, Visual Studio includes the following javascript libraries/stylesheets for you in the new project
- jquery.js - Responsible for executing jQuery scripts
- jquery.validate.js - Client-side validation
- jquery.validate.unobtrusive.js - Client-side validation
- site.js (which will be empty by default) - This is where we will add our JQuery script to open modals and perform CRUD over AJAX.
- and all stylesheets and js files related to bootstrap.
You can find all these libraries / sheets in the wwwroot folder.
Now, we will have to include an additional client-side library as well, the jQuery datatable. Right-click on the lib folder under the wwwroot folder and click on Add Client-Side Library. Search for datatables and get it installed. At the time of writing, the latest version is 1.10.21
After installing the library, we will have to add it’s reference to the entire site, yeah? For this, navigate to _Layout.cshtml under the Pages/Shared/ Folder.
Let’s add the stylesheets first. Just before the head tag closes, add the following.
Since we are already here, let’s also add the skelton of the Bootstrap Modal that we are going to use further in the article. Above the footer tag, add the HTML for the Modal. Note that the Modal Body is empty. This is because we will be filling it dynamically via jQuery AJAX with Razor Partial Views.
Finally, the scripts. Right above the @RenderSection(“Scripts”, required: false), add in the following.
It’s important to maintain the order in which the scripts are defined. ALWAYS have your jquery.min.js at the top. If there is another JS file above it, it would probably won’t work because every JQuery operation needs that the jquery.min.js is already loaded into the webpage. Understand, yeah?
Now, open up the site.js. This is usually found under the wwwroot/js/. It is not mandatory to use the site.js, but since it’s already made available throughout the website via the _Layout.cshtml we will be using it.
So, here is where we will be defining jQuery functions that is responsible for making AJAX calls to our ASP.NET Core Razor Pages and returning the partial-views to the divs so that we never notice a page reload. Makes sense? Let’s divide the entire CRUD into 3 different functions (not 4). These are as follows.
- GetAll - Loads all the customers from the database to the jQuery Datatable.
- CreateOrEdit - We will be combining the Add / Edit as the character remains more or less the same.
- Delete - Delete the customer from the datatable dynamically.
We will be building C# class for the above functions as well. But let’s build the associated jQuery functions first, yeah? Add the following to the site.js file.
NOTE that these JQuery methods NOT only work for Customer but also any other entity you throw at it. It’s written with re-usability in mind. So, it’s just one time and forget about it. Don’t really be overwhelmed with the fact that there is jQuery. It’s going to be something very generic. :D
There are three functions, GET, POST and Delete. As mentioned earlier, these functions will talk to our ASP.NET Core Razor Page which will then return partial views / html string that will be dynamically loaded on to the view of the WebApplication.
jQueryModalGet - Line 2 to 22
This particular function is responsible for rendering the particular view that has all the customers from the database filled into the jQuery Datatable. It sends a GET Ajax call to the razor page mentioned in the calling form (We will see this later.) However this is the partial view that the Get method renders.
Similarly, jQueryModalPost from Line 23 - 45
This function is responsible to display the bootstrap modal which contains the form to edit/create records. This also renders the validation errors. So, it’s a POST method that talks to a handler back in our ASP.NET Core Razor Page (We have not implemented it yet). And if the model state is valid, it closes the bootstrap modal, else displays the validation error. Get it? Here is the Crete/Edit Bootstrap Modal.
Finally, jQueryModalDelete from Line 46 to 67.
This is a very simple alert box that confirms if you want to delete the record. If yes, it sends a POST request to the delete handler of the ASP.NET Core Application and refreshes the customer table with the latest data. Everything without a single page reload. Cool, yeah?
That’s all the Generic jQuery you have to write. Now the missing pieces to the puzzle are as follows.
- Razor Partial View to Hold the jQuery Datatable.
- Razor Partial View to Add / Edit Customer.
- A way to convert Razor Views to String, so that jQuery AJAX can fetch this string and simply overwrite the existing div / DOM object on the HTML. (This was particularly tough to figure out.)
- And finally, our C# Handler methods that will return the partial views as requested by the AJAX calls.
Let’s start with the _ViewAll.cshtml. This will hold the html table definition and also the script needed to activate jQuery Datatable. Under Pages folder in the Web Project, Create a new Razor View (Empty) and name it _ViewAll.cshtml.
Ideally you would want to have a CustomerViewModel class at the Web project to keep things cleaner. But for the sake of demonstration we will refer directly to the Core Layer and use the existing customer model.
I guess the above snippet doesn’t really need an explanation. It’s the definition of table using the Model Customer from the appropriate namespace. But the points to note here is as follows.
Line 48 - An Edit button that talks to CreateOrEdit Handler passing the customer Id as a parameter and ‘Edit Customer’ as the title of the Bootstrap Modal. This will return the details of the customer selected in Edit mode via the Bootstrap Modal.
Line 49 - Similarly a delete button that POSTs to the Delete handler with the current customer Id.
Line 60 is where you activate the JQuery Datatable.
Currently, we are working with jQuery Datatable with Client-Side Processing. For scalable systems, it is better to use Server-side processing. You can find a detailed article on JQuery Datatable in ASP.NET Core – Server-Side Processing here.
Next, Let’s create the Form, CreateOEdit that will have all the fields we require. This is again a straight forward piece of code snippet. Create a new Razor Page View (Empty) and name it _CreateOrEdit.cshtml and add in the following.
Line 3 - Here we are defining the Form with the ASP Handlers set to CreateOrEdit, which we will be creating later on.
Line 45 - Submit button.
Line 50 - This activates the Validation on the Client Side.
NOTE - If you stuck at any point, you can always refer to the source code of this CRUD Application. Please find it here.
Okay, so now we have the required partial views. Let’s wire them up in our Razor Page. Let’s use the Index.cshtml page for this. Open up the Index.cshtml and add in the following.
As you can see, we will have a create button, a reload button, and finally an empty DIV over which the jQuery AJAX will fill with the Razor View (_ViewAll.cshtml).
Rendering Razor Partial View to String
Now, the question is, We have Razor Partial Views and AJAX, how do you convert Razor Partial Views to Strings / HTML. The answer is create a service that can do so. In the Web Project add a new Folder and name it Services. And in it, create a new class and name it RazorRenderService.cs
As an overview, the above service takes in the partial view name and model as the input parameters, tries to find the Razor View, renders it to HTML String and returns the string.
Let’s add this service to the DI Service Container. Open up Startup.cs/ConfigureServices and add the following to the end.
This is the final part of the puzzle. The actual Index.cs. Open it up and add the following.
Line 3 - 14 Constructor Injection of all the required Interfaces like Customer Repository, Unit Of work, Logger, and the Razor Render Service.
Line 19 - 27 Here we will have our Get All Functionality. Note that this method actually returns a PartialViewResult which will be then loaded to the viewAll DIV on the Index.cshtml by jQuery. So what happens here is you access the repository, get all the customers, and create a new partial view result with the view name and the fetched customers.
Line 28 - 37 , OnGetCreateOrEditAsync takes in the ID as the parameter and send out a JSON result that has a body with isValid and html propertly. If the Create button is clicked, the ID is 0, and the method would return the _CreateOrEdit view with a new Customer Model. If the Edit Button is clicked, it returns a view with the customer model of the particular ID.
Line 38-61, OnPostCreateOrEditAsync takes in the ID and Customer model when the Save Button on the Modal is clicked. If it was on Create Mode, it adds a new customer, else updates the existing customer. Pretty Simple and Straight forward, yeah?
Line 62-70, OnPostDeleteAsync takes in the customer ID, get the customer object and tries to delete it. After that it reloads the entire Customer dataset from database and refreshes our DataTable immediately.
There you go, that’s everything.
Pretty Seamless and already gives you some rich User Experience. This is more of a Hybrid of ASP.NET Core with Client-Side Technology. You usually expect to see such Buttery smooth interfaces via React.JS / Angular Applications. But you can achieve the awesome here as well.
That’s a wrap for this tutorial!
Summary
In this article, we learned in-depth right from setting up a solution following Clean Architecture / Onion Architecture, setting up EF Core, the Interfaces, Repository Pattern with Unit Of Work, Data Annotations, jQuery Datatables, jQuery AJAX Calls to render Razor Partial Views, Converting Razor Pages to HTML Strings, Reloading Data without ever reloading the page, Buttery smooth CRUD Operations, Bootstrap Modal and so much more. You can find the complete source code of the CRUD Application here. Do follow me as well over at Github :)
Leave behind your valuable queries, suggestions in the comment section below. Also, if you think that you learned something new from this article, do not forget to share this within your developer community. Happy Coding :D