Introduction
This article presents a very small scale blog engine developed using ASP.NET MVC, Entity Framework and SQLServer.
The basic idea behind creation of this project is to understand the ASP.NET MVC architecture by following the approach of
learning by implementing a rudimentary blog engine.
Background
It was quite recently that I started working with MVC 3.0. Before that I was doing Web Forms development.
In the last few month of working with MVC I started liking MVC a lot. I talk a lot about MVC at a local user group.
Some young developers of this local user group asked me to explain MVC architecture using a hands on approach.
I took the challenge and this application is the result of that.
Note: I did a similar project to teach n-tier architecture last year. It can be found
here: YaBlogEngine - A Tiny Blog Engine written in ASP.NET/C#[^]
I developed this application for them and developed it piece by piece with explanation on each topic.
Here in this article, I am simply giving the code for this sample application and will talk about various
design decisions I took and why. For instance, this application is developed in MCV 2.0 with ASPX views and
not RAZOR view. The reason for this was this was to keep the aspx page code on same lines as of that in web forms.
If I would have started talking about RAZOR in the first place then that would be little digressing.
Now I cannot put all the MVC theory needed for this project in this single article. So I will just show how this
code can be used and will perhaps take separate articles to discuss independent Topics of MVC separately.
Using the code
We will try to create a rudimentary blog engine with following functionality:
-
Authors can post blogs
-
Authors can manage(update/delete) blogs
-
Authors can Manage(add, update) categories.
-
Unregistered users can view the blogs and comments.
-
Registered users can view the blogs and post comments too.
Let us look at the projects structure and discuss on major design decisions so that this article will serve as a
reference guide for this project.
Database Design
We designed a very simple database for this application. The database structure for the application
looks like:
Here we have three tables:
-
Blogs
: This will contain the blog data.
-
Comments
: This will contain the comments on blogs.
-
Categories
: This will contain various categories that the blogs can fall into.
Data Access
Now we could have done the data access using classic ADO.NET easily but for this project Entity Framework
is used for data access. The major reason for this was that it will generate all the boilerplate functionality
for the Data access and at the same time it will generate the entities for the database objects. Now these
entities can readily be used as Model classes in our applications and thus we need not write our domain model classes separately.
The generated entities for the database looks like:
Repository and Unit of Work
Now the benefit of using Entity framework is that we get all the entities readily to be used as models.
But use of entity framework generate Context will lead to scattered code for data access across application.
So to prevent this we need to create a single point from where all the database operations will be done.
This class will be called as the repository class.
Now we need to create multiple repository class each mapping to the domain model of data model. Now how
will these multiple repositories use the ObjectContext
. For this we put these repositories behind the UnitofWork
object whose responsibility will be to hand over the respective repository to the controller classes.
This complete structures looks like:
This explanation for Repository pattern is too abstract for the beginners and we cannot cover the
repository and unit of work pattern in one paragraph. But the main intention was for those who know this
pattern will know that it is being used. If you don't know the pattern then simply look at the respective
classes and the functionality will be very clear.
Note: Now a question might arise, Why not use generic repositories here? Well this was simply a design
decision because the target audience of this exercise was not comfortable with generic repositories.
they needed all the predicates to be inside the repository classes and have specific repositories.
Creating the ViewModels
Now the next task was to create the view models. We needed few ViewModels
as
-
CreateBlogViewModel
: This view model will be used while creating the new Blog entry or editing/updating
and existing blog entry.
-
ViewBlogViewModel
: This view model is used when displaying a single blog on page.
-
CategoryListViewModel
: This view model is used on master page to enable category listing and category wise browsing of blogs.
-
PaginatedViewBlogList
: This view model is used to create paginated list of blogs on home page.
The details of these ViewModels
can be visualized as:
Listing all the Models
So from our all the above activities we have following model classes available to use from
controllers:
-
Blog
(Generated entity)
-
Comment
(Generated entity)
-
Category
(Generated entity)
-
UnitOfWork
(abstracts all ObjectContext
and repositories)
-
CreateBlogViewModel
(created view model)
-
ViewBlogViewModel
(created view model)
-
CategoryListViewModel
(created view model)
-
PaginatedViewBlogList
(created view model)
Controllers
We have an account controller already created when we created the project. We will use the default
membership for this project. We will also create two more controllers one for blogs and comments and other
for managing categories.
Also, we need some data in our master page and thus we need to have all the controllers create this data
while they are being instantiated. To make this easy, we created and abstract AController
class. This class
only does the job of preparing the data needed when the controllers are instantiating i.e. data that is being
used in master page. We will then derive all the controllers from this abstract class.
The controllers and controller hierarchy looks like:
Views
We have tried to keep the view simple both from the functionality perspective and the explanation perspective.
This project does not contain many partial view as it should but it is merely for the sake of simplicity. Lets look at all the
views created for this project.
Validations
We are using unobtrusive validations for this project i.e. We put data annotations in the
entity classes' and that will take care of the validations. For example to make all the fields of
blog entry as required we did the following:
[MetadataType(typeof(BlogMetaData))]
public partial class Blog
{
}
public class BlogMetaData
{
[Required(ErrorMessage="Subject is required before posting a blog")]
public string Body { get; set; }
[Required(ErrorMessage = "Blog content is required before posting a blog")]
public string Subject { get; set; }
}
Improvements Needed
This whole project has been created as a teaching exercise. It has a lot of scope for improvements. But
since this was created for teaching how to create the first MVC application following things we not done and
should be done to make this project even better.
-
Using MVC 3.0 or 4.0 with Razor views.
-
Use of generic repository.
-
Lot more partial pages to further simplify the views' code.
-
Use of WYSIWYG editor for posting blogs and comments.
-
Putting the Data access logic in a separate class library and using this library from this
application.
-
Implement more strict validation checks based on
regex
and lengths.
-
Implement client side validations.
Point of interest
This article is not meant to be a tutorial on MVC or anything else. Rather it just explains a little bit
about the attached sample application and how to use/refer it code. This sample application has been created
during a 4 hour training session I conducted to teach the MVC to web form developers.
We cannot cover all the theoretical aspects associated with this article in this single article. So I am posting
the "using the code" guide along with the sample code hoping that someone might find it useful. This is in no way a
value add for experienced programmers but beginner's might want to play around with the code. I hope this sample application
will be somewhat useful for someone.
History
-
10 April 2013: First version.