Monday 15 September 2014

Simple asp.net MVC 4 explanation

This post is mainly to assist developers (and myself) to help understand how asp.net MVC 4 works and how it fits together to create one AWESOME solution.

I was sceptic at first about asp.net MVC (coming from a drag drop asp.net web forms background) and thought it was just another way of trying to complicate the life of a developer until I started researching asp.net MVC.

This example project does not have any fancy styling, I want to put more focus on the MVC.

Each section contain examples on how to get your MVC project up and running as fast as possible.

The topics covered in this post:
  • Starting your project
  • Models
  • Views
  • Controllers
  • How MVC makes your life easier

Starting your project

Creating the project


For this project I'm using Visual Studio 2012 with MVC 4.

  1. Once in Visual Studio, create a new project by clicking: File > New > project
  2. Select ASP.NET MVC 4 Web Application and name it Simple (for this project)
  3. Select the Basic template and the Razor View engine. (You don't have to tick the Create a unit test project, I am not going into Test Driven Development (TDD) for this specific example)
  4. Click OK. Now your project will be created and we can start playing with it.
Notice the folders created:


We will mainly be working with the Controllers, Models and Views folders.

Setting up the routes


Here we are just going to change how our project starts up when you run it.

To set up your routes for this project, expand the App_Start folder and open the RouteConfig.cs class.

Find this line in the class:

                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

and change it to:

                defaults: new { controller = "Status", action = "Index", id = UrlParameter.Optional }

Notice I only changed the controller.

In any other solution you could've started with a HomeController instead of the StatusController. But I wanted to show where it finds the default route when your application starts up.

Models

The model will handle the business logic of the application. In most cases, the Model will store and retrieve data from a database.

Real world example:

The controller will send information (such as user input) to the model to be stored in the database, or the controller will send a request to a model to retrieve certain information.

This is essentially just a bunch of classes. Nothing more nothing less. Notice that when you add a model to your project, you just add a class (.cs). There is no special model black magic that you have to do. It's just a class.

To add a model, right click the Models folder and click Add > Class. Create 2 models, name one Status.cs and the other one Repository.cs

Add the code to the Status.cs class in the Models folder and add the using System.ComponentModel.DataAnnotations; namespace at the top:

    public class Status
    {
        [Key] 
        public Int32 statusID { get; set; }

        [Required(ErrorMessage="Please add a status")]
        public String statusMessage { get; set; }
    }

I have added data annotations to help us with validation. Notice that without the data annotations our model will simply just look like this (Data Annotations explained in the how asp.net MVC makes your life easier section):

    public class Status
    {
        public Int32 statusID { get; set; }
        public String statusMessage { get; set; }
    }

Add this code to the Repository.cs class to simulate records:

    public class Repository
    {
        public List<Status> getStatus()
        {
            return new List<Status> {
                new Status() { statusID = 1, statusMessage = "This is a status Update" },
                new Status() { statusID = 2, statusMessage = "Are you serious?" },
                new Status() { statusID = 3, statusMessage = "Posting my status." }
            };
        }
    }

This will be our simulated database. Both of these classes fall under the Models folder. (I'm not using any real databases for simplicity purposes. I will create a post on using databases with MVC at a later stage)

Views

This is known as the presentation layer. Views display data to your users. This would be, among other things, an HTML page.

Real world example:

Every Time you navigate to a website, you are presented with a fancy HTML page where you can make different selections, navigate to links, submit forms, etc. The fancy HTML that you see and interact with will be the View.

To add a View, right click the Views folder and click Add New Folder then name this folder Status. Now right click on the Status folder and click Add View. Name your view Index and select your view engine as Razor (CSHTML). The only checkbox that should be ticked is the Use a layout or master page checkbox. Click the button with the three ellipses on (...) and select the Views > Shared > _Layout.cshtml. Press Ok and then Add to create the view.

Notice in the example below, the view uses Razor syntax. Add the below code to your Index.cshtml view (Note: Some of this code might already be in the View):

@model Simple.Models.Status /* I hardcoded my status model here. */

@{
    ViewBag.Title = "Index"; /* dynamic variable that can be used in this view */
    Layout = "~/Views/Shared/_Layout.cshtml"; /* Uses the _Layout.cshtml "master page" */
}

<h2>Status</h2>
<ul>
@foreach (var item in ViewBag.Status) /* See #1 below for explanation */
{
    <li>@item.statusMessage</li>
}
</ul>

@using (Html.BeginForm("Index", "Status", FormMethod.Post)) /* See #2 below for explanation */
{
    @Html.LabelFor(m => m.statusMessage); /* See #3 below for explanation */
    @Html.TextBoxFor(m => m.statusMessage);
    @Html.ValidationMessageFor(m => m.statusMessage);
 
    <button name="post">Post</button>
}

#1 Here I am Iterating through ViewBag.status. ViewBag allows the setting of variables dynamically and does not need type casting. In my statusController I set ViewBag.Status = _repository.getStatus(); which retrieves the records from our Model.

#2 This form simply posts to the Index action (method) in the StatusController.

#3 Here I add a label, a textbox and use the validation message that I added on the model. the m => m.statusMessage is a lambda expression which represents our model hardcoded at the top.
Note 1: m can be anything. it can even be foo => foo.statusMessage.
Note 2: The Html.ValidationMessageFor(m => m.statusMessage); part uses the validation message that we added as a data annotation. This is nothing special, we just add the [Required] attribute above the statusMessage property in the model. See Data Annotations for models in the How MVC makes your life easier section for an example.


Controllers

Controllers control the flow of your application and processes the user input. Remember, a controller consists of classes and methods. Like I mentioned in models, there are no rituals that you have to perform to get a controller up and running and telling your application what to do.

Real world example:

Let's say you fill in a "contact us" form on a page (View), how would the application know what to do with the form once it's submitted? This is where the controller comes in. Once you press the submit button, the controller takes your input values and does something with it.

To add a controller, right click the Controllers folder and click Add Controller then name your controller StatusController and select the Empty MVC controller template.

Add the below methods to your controller  (Note: Some of this code might already be in the Controller):

    public class StatusController : Controller
    {
        Simple.Models.Repository _repository = new Models.Repository(); /* See #1 below */

        //
        // GET: /Status/

        public ActionResult Index()
        {
            ViewBag.Status = _repository.getStatus();
            return View(); /* See #2 below for explanation */
        }

        [HttpPost] /* See #3 below for explanation */
        public ActionResult Index(Simple.Models.Status model) /* See #4 below for explanation */
        {
            ViewBag.Status = _repository.getStatus();

            if (ModelState.IsValid) /* See #5 below for explanation */
            {
                //Do stuff
            }
            return View();
        }
    }

#1 I am using _repository in both of these methods, so I add it at the top to reduce redundancy.

#2 The Controller is smart enough to know that it must look under the Views folder, find the Status folder, and look for Index.cshtml.

#3 This method has been marked with the [HttpPost] attribute so that it knows to look at this method when the form has been submitted (posted). The default is [HttpGet], that is why [HttpGet] has not been added to the top method.

#4 This method accepts our model as an input. Notice that we hardcoded our model in our view and used the @Html.TextBoxFor(m => m.statusMessage); So now when we submit our form, the model will contain the statusMessage and send it to our controller.

#5 If validation has passed, we can continue doing work or saving to our database. IE, our data annotations has been adheared to (See Data Annotations on models in the How asp.net MVC makes your life easier section)

How asp.net MVC makes your life easier

Data Annotations on models


This is amazing functionality that you can add to your model. Basically, you add an attribute to a property in your model and bob's your uncle. Validation added.

Data annotations exist in the System.ComponentModel.DataAnnotations namespace. 

See below code explained:

    public class status
    {
        [Key] 
        public Int32 statusID { get; set; }

        [Required(ErrorMessage="Please add a status")]
        public String statusMessage { get; set; }
    }

The [Required] attribute marks the statusMessage as required and will display the ErrorMessage if an empty status is submitted.

The [key] data annotation will mark that specific property as a primary key.

There are a lot more Data annotations that can be found on the web.

View engines


MVC uses a different view engine which comes with its own benefits. For a detailed comparison of the 4 MVC view engines, please have a look at this Channel9 site.

Separation of Concern (SoC)


MVC divides your application into separate sections where each section serves a different purpose. Each section can be developed and updated independently. 

I hope this post helps someone understand asp.net MVC 4 better. Any comments are welcome.



No comments:

Post a Comment