Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

ASP.NET MVC: Build Your Custom Blog Engine (CMS) - Part 1 of 2 (Own ASP.NET MVC)

4.87/5 (36 votes)
20 Jan 2016CPOL29 min read 95.3K   2.1K  
Walkthrough building a re-usable blog engine which will help you create your web site using MVC while you learn ASP.NET MVC from beginning to intermediate level.

Introduction

There are an overwhelming number of articles out there about learning ASP.NET MVC, so why should you read this one?

  1. This article will take you from the beginning of generating a project using the wizard through to a complete system which will allow you to post content easily to your web site.
  2. This article will guide you to learning exactly what the ASP.NET MVC project template contains and how to use it for your own purposes.
  3. You will really learn to own the information about the template MVC project. You'll know where things happen and how they work.
  4. You will learn how to add controllers, alter Views, what the _Layout.cshtml is and why it's important, how script bundling works, the structure of the MVC project -- where things are found -- how to make the default NavBar work for your site.
  5. Shows you how to remove and customize all the generic code the VStudio project template adds to your MVC project that you probably won't use.
  6. Provides a walk-through of creating a ASP.NET MVC project using Visual Studio Community 2015 edition.
  7. Part 2 - Provides you with a re-usable component you can use to easily update your web site with content.
  8. Part 2 - See hands-on use of PartialViews, Razor, JavaScript, jQuery AJAX calls and more.

Background

First and foremost, I wanted to be able to post content to my web site extremely fast. I often encounter some interesting facts while developing some piece of code which I want to write about and make available.

I also want a simple menu at the top of my web site that allows readers to move around my site while still knowing where they are on my site.

I've tried:

  • Drupal: way too much work and annoying to customize
  • Joomla: overcomplicated and difficult to customize
  • WordPress: Of course, I've tried WordPress. I also had a PHP virus take over my site even though I kept up with the updates. I wiped the site entirely. Annoying. I think PHP has its place, but I am stunned that an entire CMS is built using it. It's not great but it's like candy for a kid and everyone uses it because it is "so easy".
  • BlogEngine.Net: Seemed to run slow on my cheap host.

What I Want from a Blogging Engine

What I really want is:

  1. the ability to create a little HTML subpage
  2. the ability to drop it into a folder
  3. new article to appear at the top of the page
  4. the article's title to appear in a navigation list on the left where a user can click each one to read previous articles
  5. for it to be simple and load relatively quickly

If that sounds interesting at all, keep on reading and I'll walk you through the creation of this customizable blog engine. We will start with the basic ASP.NET template (which has a bunch of confusing junk in it that you may never use). Let's go.

Creating the Blog Engine

Start up Visual Studio and create an ASP.NET MVC Template project.

Well, the first thing you need is a good name and I played around with this and decided on a loose Spanish translation of the English phrase One River: UnRio - pronounced oon-ree-oh.

For this article, I will use Visual Studio Community 2015 edition since it is currently the newest and it is free.

Start up Visual Studio and choose File... New Project...

You will see a window which allows you to select your project type. I find it a bit odd, because you will not see an MVC project anywhere. Instead, you have to choose ASP.NET Web Application (C#) since I will use C# for this article.

Choose the correct project type

After that, you will see a dialog which looks like the following:

Choose MVC

This is the place to choose the MVC project template. You can see that I've highlighted that choice.

There are two other choices we need to make on this dialog.

Authentication

We want to turn off all Authentication so you'll need to click the [Change Authentication] button which brings up another dialog. Individual User Accounts will be selected by default. You need to select the No Authentication choice and click the [OK] button to turn it off. That functionality is out of scope for this article.

remove authentication option

Microsoft Azure

[ ] Host in the cloud is also turned on. Go ahead and turn that off too and then click the [OK] button to continue creating your project.

A dialog similar to the following will appear as the project is created:

creating project progress bar

Run the New Project

As soon as the project is done creating, go ahead and run the project to insure everything is set up properly.

Hint: CTRL-F5 is the shortcut to build and run the project with no debugging in Visual Studio.

Once it starts up, you'll see that standard template view with the Jumbotron (large area filled with gray and [Learn more] button) :thumbsdown:.

first look at running site

Destroy the Jumbotron

We are going to destroy the jumbotron so we don't look like every other web site that has just been generated. However, the navigation bar is nice, so we'll also learn how to customize it along the way.

If you've never looked at an ASP.NET MVC project which has been created by a template, it can be quite overwhelming. Let's take a look at the project structure first so you'll know where to find things.

ASP.NET MVC Project Structure Overview

The best way to famliarize yourself with the MVC project is to look at the tree structure where all of the source files are stored for your project. Visual Studio displays this on the right side by default and mine looks like the following. I've highlighted the Content folder to start our focus there.

MVC project structure

If you break the entire project down, you basically have:

Style files (.CSS) (cascading style sheets) located in the Content folder. Site.css is the main one and there are a couple of included ones for Bootstrap. These are simply some common styles that are used by numerous projects around the world.

Controller files (.CS) in the Controllers folder. Controllers generally contain your application logic. We'll see much more about them later.

Font folder: Obviously, this project has included some special fonts it can use, but we are going to ignore those for now.

Next, you see the Models folder which is empty. That's because Models are Business Objects or Domain Objects. They are classes which represents the things in your problem (or business) domain. We will add some models to this project while showing you how they are used.

Scripts -- These are client side scripts which are written in JavaScript. This folder includes jQuery which we will use in our application.

Views - These are the CSHMTL files (Razor-powered HTML). Even though these are CSHMTL, you can think of them as HTML. The CS part simply denotes that you can add script that the Razor view engine can run to help you make your content active. We'll see exactly what this means in this project.

After all of those folders, there are some other items like the Global.asax (items which are global to the ASP.NET application) and of course your web.config which provides some configuration for your application. We will leave most of those things alone.

Which Files Will We Spend Time With?

Most of our time will be spent:

  1. creating new Models which will represent objects we want to display. These allow us to separate out the domain objects so they can be used and altered and extended more easily.
  2. creating new Controller(s) -- writing our application logic.
  3. altering the Views (CSHTML files) so they display what we want to see.
  4. altering styles in the Site.css file.

Let's start editing some code, making changes and rebuilding our project to see our changes.

First thing we want to do is remove the Jumbotron.

First Change to Project Template

Open up the Views folder and find the Home folder and open that one too.

Next, double-click the index.cshtml file and it will display in the Visual Studio editor.

It's a very simple file and it will give you your first look at Razor code. It's right at the top and looks like:

ASP.NET
@{
    ViewBag.Title = "Home Page";
}

For now, you can ignore that line. But since you're probably wondering what it does, I'll tell you. It adds a new variable named Title to the Dynamic ViewBag object. Later, the Razor rendering engine will read that value and display it somewhere.

The code we want to focus on and delete is the next five lines you'll find after that. It looks like the following:

HTML
<div class="jumbotron">
    <h1>ASP.NET</h1>
    <p class="lead">ASP.NET is a free web framework for building 
     great Web sites and Web applications using HTML, CSS and JavaScript.</p>
    <p><a href="http://asp.net" class="btn btn-primary btn-lg">Learn more &raquo;</a></p>
</div>

Highlight all of those lines and delete them.

Next, build and run the project again. Remember, you can just use CTRL-F5 to do so.

Ahhh...No more jumbotron! :thumbsup:

jumbotron gone

Take the NavBar for a Test Drive

Try clicking around on the Navigation bar. If you do, you'll see that the [Application Name] item and the [Home] menu choices do the same thing -- they load the home page (index.cshtml).

I don't like that. Let's fix it. Also, let's see how to change the color of the Navigation bar.

Where Does NavBar Code Live?

The NavBar is loaded on every page we go to on the site. It would be extremely bad to have that code on every page because if we did and something went wrong with it or we wanted to change it, then we'd have to edit every page in our web site to fix it or change it.

That's where the Shared folder (under Views) comes in. There are HTML templates which are shared on pages in there. I originally found this only by digging around for a while. The file we want to look at is the _Layout.cshtml.

This is where we are going to learn a lot because there are a lot of things happening in _Layout.cshtml.

How does _Layout.cshtml Load?

To understand that, we need to take a look in the root of the Views folder. You will see that the Views folder contains all of our current View folders (Home and Shared) and it also contains one file named _ViewStart.cshtml.

That file contains very little code and looks like the following:

ASP.NET
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

Razor Engine & Special File: _ViewStart.cshtml

The Razor engine looks for this specially named _ViewStart.cshtml file and will load it before any of the other files found in the same directory or subdirectories where it is found.

That is a bit of magic you get from the ASP.NET MVC.

Once the _ViewStart.cshtml file is loaded, the Razor directive in the _ViewStart.cshtml tells it to load the _Layout.cshtml file and then load the target file such as Index.cshtml.

So you can think of the process as something like the following:

_ViewStart flow

The point of all that is that since the _ViewStart.cshtml loads before any of the files in the Views folder and since it loads the _Layout.cshtml and since the NavBar is defined in the _Layout.cshtml, the NavBar will be included on all the pages which are defined under the Views folder.

Let's take a closer look at the _Layout.cshtml to see specifically what it does.

In the header section of the page, you'll see code which looks like the following:

HTML
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>

Razor Directives Load CSS and Modernizr Scripts

First of all, you can see that the Title references the @ViewBag.Title value to set the string that displays in the title bar of the browser.

A little further down, there are two calls to the @Styles.Render Razor directives in the head section.

Those two directives are helper methods which load all of your CSS files which are found in your application's content directory and then load the modernizr.js library which is used to insure the browser is able to support specific JavaScript that the site might use.

What Does Tilde (~) Mean?

First of all, the tilde in the path means that the ASP.NET engine should traverse to the application root and then find the Content directory. This is slightly different than /Content which is the site root. You could have more than one application running under the same site and this is how they are differentiated.

What is the Bundles Directory? It Doesn't Exist

As you've probably noticed the ~/bundles directory doesn't exist in your project.

What are bundles? Bundles are simply 1 or more scripts (JavaScript) which are all placed in one file so they can be served to the web site visitor using only one HTTP connection. ASP.NET has a bundling script built into the project and you can see this happening when the ASP.NET application starts in the Global.asax.cs file. It looks like the following:

C#
public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }

The last line is where the bundles are registered with the system so they can be used later.

Our line in the head references the bundles to load the moderniz.js script.

Use Visual Studio to Learn More

Now, if you'll right-click on the BundleConfig portion of that last line (see bolded item in previous codeblock) in Visual Studio, you can choose, "Go to definition" and it will take you code where the bundles are defined for your project. The file is named BundleConfig.cs and that file is found in the App_Start folder in your project.

go to definition

C#
using System.Web;
using System.Web.Optimization;

namespace UnRio
{
    public class BundleConfig
    {
        // For more information on bundling, 
        // visit http://go.microsoft.com/fwlink/?LinkId=301862
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.validate*"));

            // Use the development version of Modernizr to develop with and learn from. 
            // Then, when you're ready for production, use the build tool 
            // at http://modernizr.com to pick only the tests you need.
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/modernizr-*"));

            bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
                      "~/Scripts/bootstrap.js",
                      "~/Scripts/respond.js"));

            bundles.Add(new StyleBundle("~/Content/css").Include(
                      "~/Content/bootstrap.css",
                      "~/Content/site.css"));
        }
    }
}

System.Web.Optimization

The bolded using statement shows you the library which contains the bundling classes and you can investigate more at the MSDN documentation. But do know that the documentation at the site explains the library as:

Quote:

includes classes that support Content Delivery Networks (CDN) and the process of optimizing JavaScript and cascading style sheet (CSS) files in a website to reduce file size and improve page performance.

The bolded lines in the previous codeblock show you where the items which are being referenced were originally added to your project.

You can now clearly see that the ~/bundles/modernizr actually points to the ~/Scripts/modernizr-* script which is found in the Scripts folder of your project. When I look in that folder, I find one script which matches the file mask: modernizr-2.6.2.js.

You can also see that the ~/Content/css reference actually loads two CSS files found in the Content folder (bootstrap.css and site.css).

Since all of these are loaded in the Global.asax.cs startup code, they are available as soon as your application is loaded.

Before we head back to the _Layout.cshtml and look at more of the Razor code, let's take a small aside and think about what Razor really does.

What Does Razor Really Do?

Keep in mind how Razor is defined. It is a rendering engine. That simply means that it renders HTML as a view to the user. The important thing to keep in mind is where Razor runs code.

Often, a lot of View code is run at the client (in the browser) via JavaScrpt.

However, Razor is different. It is much closer to the C# that you write which is located on the server side. If you keep this in mind, it'll help you think about how/when everything is done within your MVC application.

First of all, as a segue into what Razor does, let's think about the normal request/response with a browser and a web server.

Client / Server (Browser / Web Server) Response

Normally, the browser requests a URL like: http://example.com/test.htm. The server finds the file named test.htm and sends the bytes to the browser.

However, with the Razor rendering engine, there are some extra (dynamic) parts to this process.

The browser requests a URL such as: http://example.com/Home.

The server finds the route to that URI and determines that the HomeController should be activated (instantiated and run). The HomeController action method named Index() runs. That code looks like the following snippet:

C#
public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

The HomeController simply returns the matching View() -- found in the Home directory named index.cshtml. But, keep in mind the flowchart above which shows that hte _ViewStart.cshtml and _Layout.cshtml will get involved.

Finally, we have a physical file that the web server can use for bytes which will be sent to the user.

However, first the _Layout.cshtml file is parsed by the web server ASP.NET engine and it finds Razor rendering engine directives which need to be executed. This is all happening on the server, before the user sees anything in her browser.

Razor Executes Directives

The ASP.NET engine (this is a summary, not exact) loads the Razor rendering engine to execute the directives.

Razor Generates Standard HTML

Razor generates standard HTML which it can then send to the user's browser, which the browser knows how to render.

Benefits of Razor Engine

The main benefit of the Razor engine is that it

  1. runs on the server
  2. has access to C# code and more specifically the domain objects you've created in your solution
  3. This allows you to render views of the data contained in your domain objects easily and efficiently

Now, let's continue examining the _Layout.cshtml. The next thing we'll see are some helper methods that the Razor engine provides to create links on your web pages.

Razor Helper Methods

Back in the body content of the _Layout.cshtml, the next interesting thing we see is a directive which looks like:

C#
@Html.ActionLink("Application name", "Index", "Home", 
                  new { area = "" }, new { @class = "navbar-brand" })

That Razor method, Html.ActionLink, builds a link which is displayed on our web page. This is a perfect example of Razor generating HTML which is then sent to the client.

View Page Source: You Won't See Html.ActionLink

If you run the program and let the Home page load in the browser and then right-click the page and choose View Source in your browser, you will not find that code.

That's because that code only exists on the Server side. The Razor view engine has run and converted it into standard HTML which was then sent to the browser.

Instead, you'll see something similar to the following (see the bolded line in the HTML source below):

HTML
<div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" 
                 data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="/">Application name</a>

It's a HTML <a> tag (link) with the text "Application name". Also notice that the class has been set to navbar-brand which is a CSS style which makes it look as it does in the menu.

Html.ActionLink Parameters

Looking back at the call to the ActionLink, you can see that:

  1. the first parameter is the text which will be displayed
  2. the second parameter is the Action name : method in the controller -- this one is Index
  3. the third parameter is the Controller name: this one is Home
  4. the fourth parameter is a route value (more on routes in another article): in this case, the code generates a new blank area route.
  5. the fifth parameter is any HtmlAttributes you want to add: in this case, it adds the CSS style of navbar-brand

What Happens When User Clicks Link

This tells us that when the user clicks the link then the server should load the HomeController and call the Index() action method:

As we said before, this is server side code and this code is actually .NET code (C# in our case) which calls a method in a .NET library named System.Web.Mvc.Html.LinkExtensions.

You can view all of the different types of Extensions that can be called in the MSDN documentation at this link (opens in new tab/window).

More NavBar Code

You can see that there are some ActionLinks added in the following snippet from _Layout.cshtml.

HTML
<ul class="nav navbar-nav">
     <li>@Html.ActionLink("Home", "Index", "Home")</li>
    <li>@Html.ActionLink("About", "About", "Home")</li>
    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

These calls only require the first three parameters (Link text, Action, Controller) to define the link.

Before we look at the next part of the _Layout.cshtml, let's take a moment to think about why the NavBar is in this file.

Big Picture Thinking

Keep in mind that a web site's NavBar is something that you want to be available from every page within the site.

Since mature, experienced Developers (advanced developers) know that they do not want to duplicate code ASP.NET MVC has provided a way create code once and re-use it throughout the project. On top of that, we see that ASP.NET MVC has provided a way to load these re-usable elements as a Layout which is easily added across all of your pages.

What If You Don't Want Default Layout On A Page

It is as easy as adding a directive to the top of your CSHTML page which will set @Layout = <new layout>.

Then, when the page loads, it will override the default value and use your special Layout.

Let's take a look at how to create a new layout and apply it, because now you know quite a lot about how all this works it'll make sense to you.

Hands On: Let's Write Some Code

In this section, we are going to do the following:

  1. Add a new NavBar element (link)
  2. Add a new Controller -- which will load the page associated with the new NavBar link
  3. Add a new View -- the target page of the associated HtmlLink
  4. Add a new Layout -- which will be used on the new target View

This will allow us to pull all of what you've learned together.

Add a NavBar Element

This is very easy. Open the _Layout.cshtml file in Visual Studio. Go down to where the last @Html.ActionLink is located (the one for Contact) and add a line which looks like the following:

HTML
<li>@Html.ActionLink("Extra", "Index", "Extra")</li>

If you'll add that code and then run the application again, you'll see that the NavBar now contains a new menu item with the text Extra.

navbar menu changed

However, since this link routes to the Index action of the ExtraController, it will give you an error if you click it, because that Controller does not yet exist. Let's add it to the project.

Add the New Controller

Right-click the Controller folder on the right side of your project and choose the Add...Controller...menu items.

add new controller

A dialog will appear and we want to choose an MVC controller which has basic read/write Actions (methods) already defined. It'll look something like the following:

basic MVC controller

Once you choose that template controller, go ahead and click the [Add] button.

Controller Naming Convention

After that, it will ask you for a name for your controller. It will probably provide a name like DefaultController where the Default portion of the text is highlighted. That's because the convention for naming a Controller follows a patter like <Noun>Controller where the <Noun> portion is a noun which describes your Controller.

In our case, we want it to be named ExtraController, so type Extra (to name it ExtraController) and click the [Add] button.

The class will be generated and Visual Studio will display it for editing.

The top part of the class will look something like the following:

C#
namespace UnRio.Controllers
{
    public class ExtraController : Controller
    {
        // GET: Extra
        public ActionResult Index()
        {
            return View();
        }

Menu Item Still Doesn't Work

The important part to us is that now we have a valid Index action on an ExtraController. However, our Extra menu item link still will not work.

If you build and run again and click the Extra link, you'll get an error which states something like:

The view 'Index' or its master was not found or no view engine supports the searched locations. 

That's because the Index() method returns a View() but the ASP.NET engine cannot find any matching view. A matching view would be one that is named ExtraView.

Add An Extra View

Let's add a view now so everything will work.

Interesting Item: I do see that under the Views folder, there is now a new folder named Extra even though we weren't the ones who created that folder. Visual Studio created that item for us because it knows that our ExtraController will route to the \Views\Extra folder.

Go ahead and right-click that folder and choose Add...View...

add new view

Visual Studio will display a dialog box to guide you through the creation of your new View.

Notice that the word View is highlighted so that when you type it will be overwritten.

A view name is simply the name of the page. In our case, we simply type Index (to create the Index.cshtml file inside the \Views\Extra folder).

We are going to keep the default template choice: Empty (without model) - that's an option for later.

Finally, notice that last checkbox (Use a layout page) and the associated text box which is empty.

Take note of the message on the dialog window. It states, (Leave empty if it is set in a Razor _viewstart file).

That's talking about the _ViewStart.cshtml file we've already discussed.

For now, leave that empty and click the [Add] button.

Visual Studio Generates View File

Studio will work and generate the Index.cshtml file (and place it in your Views\Extra\ folder. Finally, Visual Studio will display the file for editing.

The entire file is only five lines long, including blank lines:

HTML
@{
    ViewBag.Title = "Extra";
}

<h2>Extra</h2>

Now, if you'll build and run, you'll see that the Extra menu item now loads this View.

Extra view is added

Notice One Thing, Try Another Thing

That last image is what displays after you click the Extra menu item at the top. It loads our ExtraController which returns the View() represented by Extra\index.cshtml.

Notice that the NavBar does not indicate to you which menu item you last clicked. I think it should and we are going to change that, but first let's alter something extremely small to show you how the ViewBag dynamic object works.

The original template creators missed out a small opportunity because they could've used the value stored in ViewBag.Title to set the text in the <H2> element.

ViewBag: Get A Value

To show you how you might use Razor to read the value in the ViewBag, let's change the code on the \Views\Extra\Index.cshtml so that instead of the following:

HTML
<h2>Extra</h2>

We will have this line:

HTML
<h2>@ViewBag.Title</h2>

Since we know that we just set the value in the ViewBag named Title to a string equal to "Extra", we know that you won't see any difference on the page, but you will at least get to see that Razor is doing the work now.

Render Menu Differently Depending Upon ViewBag Value

Now we will use the ViewBag to store a value to indicate which page is loaded so we can alter the style on the associated menu item so users can tell which item was clicked and understand where they are in the site simply by looking at the NavBar.

Dynamic Style Based Upon Choice

First of all, you have to understand a bit about Bootstrap styles because the navbar is actually a Bootstrap defined style. To learn more about Bootstrap, you can go to the official site: http://getbootstrap.com/ (opens in a new tab / window) and read up.

But for our purposes, I will just explain a little bit about it to you. The short story to the much longer one is that if you set a class on the list item <li> which represents the menu item (in _Layout.cshtml).

Yes, I'm talking about the code we have already looked at which looks like:

HTML
<li>@Html.ActionLink("Home", "Index", "Home")</li>

That's the Home menu item.

If we alter that slightly adding a Bootstrap style, we will see that the item will appear to be selected.

Go to _Layout.cshtml and change the line so it looks like:

HTML
<li class="active">@Html.ActionLink("Home", "Index", "Home")</li>

The bold part is all we added.

Now, build again and run and you'll see a slight difference in the style on the Home menu item.

It's somewhat subtle because it is a variation of black and not exactly a profound difference.

bootstrap active style

We Want to Dynamically Set That Style

However, we want to dynamically set that style so that it only displays as active when the associated link is clicked.

That's where Razor is supposed to help us out. What we want to do is set a style based upon some value.

Understanding ASP.NET MVC Event Order

Since we understand the ASP.NET MVC Event order we can begin to create a solution. We know that when the user clicks the menu item, the associated Action on the Controller fires. That means we can react to the user taking certain actions.

Add Item to ViewBag In Controller

I suggest as an easy way to do this we simply set a value on the ViewBag that represents the clicked item.

We will do that in the Controller code before it returns the View().

We'll do this first on the ExtraController so open up ExtraController.cs in Visual Studio and alter the Index() method to look like the following:

C#
public class ExtraController : Controller
    {
        // GET: Extra
        public ActionResult Index()
        {

            ViewBag.selectedItem = "extra";
            return View();
        }

The only code we added here is that one bold line.

Since the ViewBag object is a dynamic object which is global to the application. We can add properties to it at any time. In this case, we just did by adding the selectedItem property and setting that property to a string with a value of "extra".

What Are We Going to Do With That Value?

We can now get the value of ViewBag.selectedItem anywhere within our application. And since Razor can easily get the value, we can use it to do special things in our views.

Since we know that we need to alter the look of the NavBar item and that code is in the _Layout.cshtml, we need to switch back over to that code now.

First of all, remove that class code we previously added to the Home link and make sure all of your links now look like the following again:

HTML
<ul class="nav navbar-nav">
    <li>@Html.ActionLink("Home", "Index", "Home")</li>
    <li>@Html.ActionLink("About", "About", "Home")</li>
    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
    <li>@Html.ActionLink("Extra", "Index", "Extra")</li>
 </ul>

Add the Dynamic Razor Code

What we need to do now, is check to see if the value of ViewBag.selectedItem == "extra".

If it is, then we want to set a CSS style class = "active", but if it is not, we do not want to set the CSS class.

After a bit of working, I got to the following code that we want to set on our last link -- eventually we will set them all.

HTML
<li class = @(@ViewBag.selectedItem == "extra" ? "active" : "")>
@Html.ActionLink("Extra", "Index", "Extra")</li>

That is all one line of code and should replace the line which looks like:

HTML
<li>@Html.ActionLink("Extra", "Index", "Extra")</li>

If you notice, all I really did was add some code into the area inside the <li> tag.

The added code itself (without all the other stuff) looks like:

HTML
class = @(@ViewBag.selectedItem == "extra" ? "active" : "")

Call A Razor Function

All this really does is call a Razor function @( ) and that function implements what is called the ternary operator. Basically a ternary operator is an easy way to do an evaluation and return a value. A ternary operator takes on the form of :

evaluation-item ? true : false

evaluation-item ? if true return this thing : if false, return this thing

Our ternary operator does the following:

  1. determines if @ViewBag.selectedItem == "extra"
  2. if it is equal to the string extra, then it returns the string "active"
    1. if the ternary operator returns the string "active", then the CSS class will be set to "active" and the item will look as if it has been selected.
  3. if it is not equal to "extra", then it will return an empty string "" and the CSS class will not be set and the style will not be changed.

Build the application and run it and click any of the menu links and you'll see that only the Extra one ends up being set to an active style when you click it. It's a nice way to indicate to the user that she has chosen this menu item.

Change All Controllers and All NavBar Menu Item Links

Now all you have to do is change all of your Controllers so each one sets the ViewBag.selectedItem to a unique string (menu text is best) and then add the associated script to each element in the NavBar and when you click each link, it will have a selected style while the others will look normal.

Here is the final code for the NavBar in the _Layout.cshtml. You'll have to add the proper values in the Controllers so they are set.

HTML
<ul class="nav navbar-nav">

<li class = @(@ViewBag.selectedItem == "about" ? 
 "active" : "")>@Html.ActionLink("About", "About", "Home")</li>

<li class = @(@ViewBag.selectedItem == "contact" ? 
 "active" : "")>@Html.ActionLink("Contact", "Contact", "Home")</li>
<li class = @(@ViewBag.selectedItem == "extra" ? 
 "active" : "")>@Html.ActionLink("Extra", "Index", "Extra")</li></ul>

Note: I removed the Home link, since the [Application Name] item is the same thing and the home link is redundant. I also figure that if you are on the home page then none of the links are selected.

Now, you can see if whenever the user clicks a menu item she can see where she is in the site.

Image 16

Bad Colors are Difficult to See

I don't like how subtle the difference between the selected item and the non-selected items are however, so I want to show you how to change the NavBar colors.

Again, this is just about digging through the Bootstrap styles and find them.

What you will find is that you want to change the background-color of the NavBar class.

The easiest way to do that is to open up the Site.css and add a new style which will apply.

Add the following line to the bottom of your Site.css file:

CSS
.navcustom{background-color: #0033CC;border-color:black; }

This defines a new CSS class style named navcustom. You can see that the background will be #0033CC which is a blue.

More Change To _Layout.cshtml

You know why we do so much in this file? Because it is a single place of change that affects the whole site. That is a good thing in the development world.

Find the NavBar in _Layout.cshtml and add the new CSS class.

The code will look like the following now:

HTML
<body>
    <div class="navbar navbar-inverse navbar-fixed-top navcustom">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" 
                 data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Application name", "Index", 
                "Home", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">

The only change I made is the one bold word added above.

That adds the CSS class to our NavBar. Rebuild and run the application and now you can see a drastic difference when you select a menu item.

new CSS style applied to navbar

Consider How Easy Extension Will Be

Now that you understand the NavBar -- which is a large portion of the default template, you will understand MVC much better. Also, can you see how simple it is now to extend this site so that you can have multiple new menu items?

You can simply add the new links, controllers and views in a simple structured way and have your customized site in minutes. As soon as you add the items, they will all update properly too.

And most importantly, if you've stuck with this article all the way through, you've learned a lot about ASP.NET MVC.

Summary

If you followed this walk through, you really own the ASP.NET MVC template project. You know where almost everything you see comes from and now have a much better idea of how to customize the template to begin building an applicaton / web site that reall is your own.

I hope you've enjoyed the article and will chime in with your ideas.

Foundation Set: Next Article - Blog Engine

This article got a bit out of hand since I wanted to set a firm foundation, but now when we discuss the creation of the Blog Engine in the next article, you will be able to follow along very easily. After that article, you'll have a solid web application ready for use on your own web site.

History

  • 20th January, 2016: First version of article

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)