In this tip, you learn how to create a custom controller base class that exposes actions for performing common database operations such as displaying, inserting, updating, and deleting data.
Whenever you write code and you discover that you are writing the same type of code over and over again, that is a good time to stop and consider whether you are wasting huge amounts of time. Yesterday, I discovered that I was in this very situation while building a database-driven ASP.NET MVC web application. I needed to perform the same standard set of database operations – display data, update data, insert data, delete data – for each of the database tables in my application. The dreadful prospect of having to write the exact same code over and over again inspired me to write today’s ASP.NET MVC tip of the day.
An MVC controller is just a class (a Visual Basic or C# class). Classes support inheritance. So, if you find yourself writing the exact same logic for your controller actions, it makes sense to write a new base class that contains the common set of actions. In this tip, we are going to create a base controller class that performs standard database operations. Keep in mind that you can create base controller classes for other types of common controller actions.
I created a base controller class named the DataController class. This class supports the following public methods:
- Index() – Displays all of the database records in a database table
- Details() – Displays a single database record from a database table
- Edit() – Displays a view that contains a form for editing an existing database record
- Update() – Updates a database record in the database
- New() – Displays a view for inserting a new database record
- Insert() – Inserts a new database record into the database
- Delete() – Deletes an existing record from the database
Since each of these methods is public, each of these methods is exposed as an action. You can invoke any of these methods by typing the right URL in your web browser’s address bar.
The DataController class also supports several protected methods:
- DBSave() – Either inserts or updates a database record
- DBInsert() – Inserts a new database record
- DBUpdate() – Updates an existing database record
- DBDelete() – Deletes an existing database record
- DBGet() – Gets a single database record
Since these methods are protected, they cannot be invoked through a URL. However, you can call any of these methods within your derived controller class. These are useful utility methods that you can call from a derived controller’s action methods.
Finally, the DataController class supports the following properties:
- DataContext – The LINQ to SQL data context.
- Table – The LINQ to SQL Table.
- IdentityColumnName – The name of the identity column contained in the database table.
These properties are also protected. You can use them from within your derived controller class, but they are not exposed as controller actions.
The DataController is a generic class. When you create a controller that derives from the DataController class, you must specify the type of database entity that the DataController class represents. The DataController class works with LINQ to SQL. Before you use the DataController class, you must first create your LINQ to SQL entities that represent your database objects.
For example, Listing 1 contains a HomeController class that derives from the DataController class. Notice that the Movie type is passed to the DataController class. The Movie class is a LINQ to SQL entity created with the Visual Studio Object Relational Designer.
Listing1 – HomeController.vb (VB)
1: Imports System
2: Imports System.Collections.Generic
3: Imports System.Linq
4: Imports System.Web
5: Imports System.Web.Mvc
8: Namespace Tip4.Controllers
9: Public Class HomeController
10: Inherits DataController(Of Movie)
12: ''' <summary>
13: ''' Show Movies in a Category
14: ''' </summary>
15: Public Function Category(ByVal Id As Integer) As ActionResult
16: Dim results = From m In Me.Table Where m.CategoryId = Id Select m
17: Return View(results)
18: End Function
20: End Class
21: End Namespace
Listing1 – HomeController.vb (CS)
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Web;
5: using System.Web.Mvc;
7: using Tip4.Models;
9: namespace Tip4.Controllers
11: public class HomeController : DataController<Movie>
14: /// <summary>
15: /// Show Movies in a Category
16: /// </summary>
17: public ActionResult Category(int Id)
19: var results = from m in this.Table where m.CategoryId == Id select m;
20: return View(results);
Because the HomeController class derives from the DataController class, the HomeController class exposes Index(), Details(), Create(), New(), Edit(), Update(), and Delete() actions automatically. Because the Movie entity is passed to the DataController, the HomeController enables you to perform these actions against the Movies database table.
Before you use the DataController class, you must add a connection string named dataController to your application’s web.config file. You can copy the connection string generated by the Visual Studio Object Relational Designer and rename the connection string dataController.
You must still create a set of views to use the DataController class. You need to create the following set of views:
In tomorrow's tip, I'll show you how to create these views just once for all of your controller classes by creating Shared Views. But, that is tomorrow's topic. Back to the subject of the DataController.
Unfortunately, the code for the DataController class is too long to paste into this blog entry. You can download the DataController, and try it out by experimenting with the sample project, by clicking the Download the Code link at the end of this blog entry.
The sample project contains the four views listed above. You can use the sample project to display, insert, update, and delete records from the Movies database table. For example, Figure 1 contains the page generated by the Index.aspx view.
Figure 1 –The Index.aspx View
My expectation and hope is that there will be hundreds of custom base controller classes created by developers actively working with the ASP.NET MVC framework when the framework has its final release. I can imagine base controller classes used in a number of different scenarios: authentication, shopping carts, product catalogs, and so on. Anytime that you need to include a standard set of actions in more than one application, it makes sense to create a new controller base class.Download the Code