ASP.NET MVC Tip #4 – Create a Custom Data Controller Base Class

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
   6:  
   7:  
   8: Namespace Tip4.Controllers
   9:     Public Class HomeController
  10:         Inherits DataController(Of Movie)
  11:  
  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
  19:  
  20:     End Class
  21: End Namespace
  22:  

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;
   6:  
   7: using Tip4.Models;
   8:  
   9: namespace Tip4.Controllers
  10: {
  11:     public class HomeController : DataController<Movie>
  12:     {
  13:  
  14:         /// <summary>
  15:         /// Show Movies in a Category
  16:         /// </summary>
  17:         public ActionResult Category(int Id)
  18:         {
  19:             var results = from m in this.Table where m.CategoryId == Id select m;
  20:             return View(results);
  21:         }
  22:  
  23:  
  24:     }
  25: }

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:

  • Index.aspx
  • Details.aspx
  • Create.aspx
  • Edit.aspx

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

image

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

Discussion

  1. http:// says:

    This is exactly what I’m looking for.
    I have a project that does CRUD in many places and have abstracted those operations but not as far as controller level.
    Thanks Stephen, keep up the good work.

  2. panjkov says:

    would it be appropriate to instead of controller use repository ? how this controller influences testability of controllers?

  3. http:// says:

    I tried to run the code i am getting the following error

    Compiler Error Message: CS1705: Assembly ‘TaskList, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’ uses ‘System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35′ which has a higher version than referenced assembly ‘System.Web.Routing, Version=0.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35′

    Source Error:
    [No relevant source lines]

    Source File: Line: 0

    I am using visula web developer Express SP1. Do I need Visual Studio?

  4. Thanks Stephen,
    I’ve just started exploring asp.net MVC, and this seems very helpfull.

  5. JayR says:

    Hi Stephen.

    Thanks for this sample and great info, i’m new in ASP.Net MVC. btw, I copied your codes and tried to run in my application and i got this error “Object reference not set to an instance of an object.” when i click the edit, delete or for details link. The error pointed in
    “return this.DataContext.Mapping.GetMetaType(typeof(T)).DBGeneratedIdentityMember.Name;”

    Hope you will help me. Tnx in advance

  6. JayR says:

    Hi stephen.

    kindly disregard my previous post because i already solved it. as a solution for that, I checked my Table columns and reassign my id as auto..

    tnx again for this great sample.. I learn a lot from your blogs and hope you will continue to share your knowledge.. u’re da man!

    tnx. more power and success.

    -jayR

  7. almny says:

    Thanks for this sample and great info, i’m new in ASP.Net MVC
    and it will useful to me

  8. Sujith says:

    HI,
    I want to implement a create functionality from a popup how can i invoke a create method from the popup(which is a .ascx user control)Please help.
    =================================================
    Thanks in advance

  9. Shanthi says:

    How can i select first 10 records from the controller which i will be displaying in the index.aspx page. My code is something like this

    [AcceptVerbs("GET")]
    public JsonResult MyFavourites()
    {
    var context = new SnapDBDevEntities(ObjectContextConnection.GetSnapString(“SnapDBDevEntities”));
    var model = from ur in context.UserMyReports
    where ur.UserID == User.UserID
    select new
    {
    ur.Report.ReportName,
    ur.ReportID,
    ur.Report.SortBy
    };

    return Json(model.ToArray());
    }

  10. –Thanks for sharing very significant blog.

  11. frewq I tried to mock a call to a Linq to SQL query, but I am struggling.

  12. fg2 I tried to mock a call to a Linq to SQL query, but I am struggling.

  13. f32 I tried to mock a call to a Linq to SQL query, but I am struggling.

  14. very nice info at this post thanks!!!

  15. Hey this is a nice site i love it
    buy viagra pills is the best to get a huge erection for hrs I wife is happy.
    now my sex life is rebirth my wife is satisfy i got more energy and a longer erection is fabulous

  16. Thanks for this sample and great info, i’m new in ASP.Net MVC

  17. Buy Viagra says:

    this is the best post that I find in long time.
    Marianna J. Turner

  18. cocoyu113 says:

    You really can’t go wrong with the gift of good things to eat.lace front wigs
    You can give out some promotional sweets, or boxes of savories to clients, customers and employees.

  19. coupon codes says:

    Thanks for this sample and great info, i’m new in ASP.Net MVC

  20. 343222222
    I believe it is a promising (currently version 4.0). So I would stick with it.. thanks

  21. Hey really good one..
    thanks for sharing..

  22. Nathanial says:

    I am using visula web developer Express SP1. Do I need Visual Studio?

    swingers clubs toronto |web design toronto |cheap toronto web hosting

  23. klip izle says:

    Thanks I’ve just started exploring asp.net MVC, and this seems very helpfull.

  24. HD Video Converter says:

    As the users of HD Camcorders like Sony, Canon, Panasonic, this HD Video Converter is necessary to help us convert hd Video easily and quickly. The Converter for HD provides several practical editing functions to help you achieve ideal output effect. Trim function is to cut videos into clips which you can just convert and transfer to your player. Crop function helps you remove black bars around the movie. You could use Effect function to adjust video brightness, contrast, saturation and more parameters. More powerful and considerate functions are waiting for you to explore.
    TS Converter l TOD Converter l TRP Converter l H.264 Converter