Click here to Skip to main content
14,458,169 members

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

Rate this:
4.87 (11 votes)
Please Sign up or sign in to vote.
4.87 (11 votes)
2 Feb 2016CPOL
After working through this article you will have a novel way of easily posting new blog articles which will auto-update the content on your site and you will have learned the C# ASP.NET MVC code to do this.

Introduction

This is the second part of a two part series.

You can read the first part at: http://www.codeproject.com/Articles/1072781/ASP-NET-MVC-Build-Your-Custom-Blog-Engine-CMS-Part (opens in a new tab / window)

The first part covers how to manipulate the Visual Studio MVC template project into something you may actually want to use.   Along the way you get a good look at MVC development.

Why should you read this article?

This article will step you through the design and code for creating a component which

  1. you can drop into your ASP.NET MVC web site
  2. provides you with an easy way to create a blog page -- will iterate documents so when you add a new one it will appear as the current article and topmost in your list of articles

What This Component / Article Is Not

If you are looking for a complete blogging / CMS (Content Mgmnt System) (Joomla, Drupal, WordPress) you are going to be disappointed.  There's much more to add to this component.  This is a 'Get 'ur dun!' kind of a component.  Yet, I do believe you will learn a lot from examining the design and you will see that you can build upon the design I've created.

Summary of Functionality

I want to easily post new articles to my site and have them appear as the newest content at the top of the page and have them add themselves to the list of links of all my articles.

It'll look like the following:

blog engine complete

  1. Hovering over an item on the left changes the style to provide user feedback that is a clickable link to another article.  
  2. When the user clicks one of those article items, the content loads asyncrhonously into the div on the right.
  3. The article list loads dynamically and can updated at any time to deliver new content to users.

However, there will definitely be room for improvement.  

Things You May (Should) Question In the Design

As you become involved with the code you are going to uncover items in the design that can be improved upon.

One glaring item is the fact that I use a flat file as a table of entries of my blog articles.  This is simply because I didn't want to go about teaching all the database connection, stored proc stuff and all that bother.  That's for later.  However, you will notice that you can easily extend the code so yours does read from a database instead of the flat file.

If you are okay with that and you're still interested -- I hope you are -- let's get started.

Background (Related to Part 1)

One thing I have thought about is that I want the Blog Engine to be a drop-in assembly (dll) that you can place in your bin directory and get the benefit instantly.  That dll will have the name UnRio.dll (One River) which will be separate from your site's (and miine) default name.   

However, in the first article I named the entire project UnRio.  For this project you will see that I've renamed it to BasicMVC so I can work out the details of how the UnRio blog engine will work within any site.

Get The BasicMVC Base Project

If you would like to follow along as we build the application one step at a time, go ahead and download the BasicMVC_begin.zip file, unzip it and open the project in Visual Studio (I'm using Community Edition).

That code is the exact code from the first article except renamed into this new BasicMVC project.

SideBar : Community 2013 Edition Versus Community 2015

I discovered (the hard way) that there is one slight difference in a 2013 ASP.NET project versus the 2015 based one when I attemped to open the project on an older computer which had 2013.  Only after running did I receive an error which caused the app to crash.  It looked like the following:

compilation error

This was odd because the error states: [No relevant source lines]

The important part of the error message is:

Compiler Error Message: CS1617: Invalid option '6' for /langversion; must be ISO-1, ISO-2, 3, 4, 5 or Default

As you probably know Community 2015 uses a newer compiler to build the code.  I made one change in the web.config to make the project compile under both 2015 and 2013.

The line I changed looks like (focus on bold part):

<system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" warningLevel="4" compilerOptions="/langversion:5 /nowarn:1659;1699;1701">

I changed the /langversion:6 (for Community 2015) to a 5 as shown above and it worked in Community 2013.

Sidebar : NuGet

Also, if you get the source code from this project and open it in Visual Studio then the first time you build the project you will see NuGet retrieving the MVC dependency assemblies (DLLs).  It does this by looking at the packages.config file found in the project and downloading the appropriate versions of those DLLs.  

You will see a window which looks like the following when this occurs:

nuget

This allows you to get the exact versions of the DLLs which are included in the project without me having to include them in the project (making the project download much smaller).

Now, back to our regularly scheduled article.

Set Up the Project

The first thing we need to do is load the BasicMVC project in Visual Studio 2015 Community edition

Next, let's add a new project named UnRio to the solution.  

That project should be a Class Library (as shown in the next image), not the Class Library (portable).

add new project

After you add the new project, you can then add it as a reference to the BasicMVC project, since BasicMVC will depend upon it to display your blog articles.

Right-click the References item in the BasicMVC project and click the Add References... menu item which appears.

add reference

Choose the Projects item on the left and then select the UnRio checkbox and click the OK button.

select project

Now we're ready to add some code.  

The first thing we need is something to represent (model) our blog articles.  I will create a simple BlogArticle class and add it to the UnRio project.  It will look like the following:

namespace UnRio.Models
{
    public class BlogArticle
    {
        private int id;

        public int Id
        {
            get { return id; }
            set { id = value; }
        }
        private string category;

        public string Category
        {
            get { return category; }
            set { category = value; }
        }
        private string title;

        public string Title
        {
            get { return title; }
            set { title = value; }
        }
        private string relativeFilePath;

        public string RelativeFilePath
        {
            get { return relativeFilePath; }
            set { relativeFilePath = value; }
        }
        private DateTime created;

        public DateTime Created
        {
            get { return created; }
            set { created = value; }
        }
    }
}

Transformational Design: Seeing the Steps

 You can see that this class is extremely simple.  It is no more than a bunch of properties which make up my BlogArticle.  I'm keeping it very simple so you can see each design step as I go.  At this point I am just trying to get the BlogArticle to be a read item.  I'm not worried about writing BlogArticles to any database or file.

The Design Could Be Much Better

The design could be much better.  Please don't get too caught up on the fact that we could do all of this better.  I'm trying to get to the functionality that I want first and then I can refactor.  I'm still building on basic OOP tenets and SOLID (wikipedia article opens in new tab) principles, but for now I just want to get the thing working and explain it to you.

Continuing on, I know that I am going to need a collection of blog articles so I can iterate through them somehow and display them to the user in a view so that leads me to create the BlogArticleRepository class.

That class will look like:

using System;
using System.Collections.Generic;
using System.IO;

namespace UnRio.Models
{
    class BlogArticleRepository : List<BlogArticle>
    {
        private string rootPath;
        private string blogFile;

        public BlogArticleRepository(string rootPath, string blogFile)
        {
            this.rootPath = rootPath;
            this.blogFile = blogFile;
            GetAllBlogArticles(false);
        }

        public void GetAllBlogArticles(bool? forceReload)
        {
            if (this.Count == 0 || (forceReload == true))
            {
                this.Clear();
                LoadBlogArticlesFromDataStore();
            }
        }
        
        private void LoadBlogArticlesFromDataStore()
        {
            string[] allLines = File.ReadAllLines(Path.Combine(rootPath,blogFile)); 
            foreach (string line in allLines)
            {
                try
                {
                    string[] allItems = line.Split('|');

                    BlogArticle ba = new BlogArticle();
                    ba.Id = Convert.ToInt32(allItems[0]); //id 1; newest first (top of file)
                    ba.Title = allItems[1]; // "Biggest Tech Article Ever";
                    ba.Category = allItems[2]; //"Tech";
                    ba.RelativeFilePath = allItems[3];// "TechBlog1.htm";
                    ba.Created = DateTime.Parse(allItems[4]); // 2015-03-31
                    this.Add(ba);
                }
                finally
                {
                    // if any fail, just move to the next one
                    // do not stop the app for any reason!
                }
            }
        }

    }
}

BlogArticleRepository : What Does It Do?

The BlogArticleRepository allows me to easily create a list of BlogArticles.  The work of loading the BlogArticles is really all done in one place : LoadBlogArticlesFromDataStore()

As you can see, that method simply loads articles from a pipe-delimited text file.

Example Text File

I've included the example text file in the code download.  It's named blog.dat and looks like the following:

3|Visual Studio's Greatest Hits|Visual Studio|VisStudio1.htm|2015-04-02
2|Develop For Android|Android Dev|AndroidDev1.htm|2015-04-02
1|Biggest Tech Article Ever|Tech|TechBlog1.htm|2015-03-01

Obviously, this is a pipe-delimited file with 5 fields as follow:

  1. id
  2. article title
  3. article category (simple way to organize your articles later)
  4. filename (HTML which contains the article)
  5. publish date -- will be displayed in view so users know the age of the article

Currently, there are just three articles which will load and eventually be displayed by some view.

I've also created sample HTML files which will be loaded for each of those entries.  Of course those sample HTML files are named:

VisStudio1.htm, AndroidDev1.htm and TechBlog1.htm and you can find all of those along with the blog.dat with the project files download inside the blogFiles directory.

This completes the work we need to do in the UnRio project.  Now we want to move back to the BasicMVC project so we can write the code which will use the UnRio library.  That will help it all come together much better.

Setting Up BasicMVC to Use Our Blog Engine (UnRio Library)

Consider BlogArticle List In Memory

The first thing we want to consider is that our list of Blog Articles is the same list no matter which user hits our web site.  That means, we only need one list of Blog Articles in the application memory.  Once the list is loaded in memory then that list should be read from for every user's session.   That leads us to the Global.asax and Global.asax.cs since that is where ASP.NET MVC Application-wide resources can be loaded.

The Visual Studio project generator has already created a little code for us in that file, since the ASP.NET engine initializes some things when the application starts.  That code looks like the following (before we touch anything).

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

You can see that the Application_Start() method runs and it is obvious that this is what runs when your ASP.NET MVC web application starts running.  That's what we are looking for too, since we want to do a one-time load of our BlogArticle collection.

We just need to add a reference to our BlogArticleRepository in this application start up too.

Static (Application Global) Blog Article List

However, we need to create a static (application global) instance of our collection of blog articles ( List<BlogArticle>) so that we have one global list of blog articles in memory.  That way once they are loaded, then they can be used to create the View for each user who views our blog site.

Reasons This Is A Good Idea

This is a good idea because it also means that the resource intensive work of loading the articles from the blog.dat file (I/O intensive) will only be done at application startup.  There is no need to load this list for every user session that occurs.  

Let's take a look at how easy it is going to be to load our list of blog articles and a challenge related to locating files within a web server.

Using BlogArticleRepository

To load up our list of blog articles we simply add a using statement to the Global.asax.cs and then new up a BlogArticleRepository.  It will look like the following (bolded items have been added):

using UnRio.Models;

namespace BasicMVC
{
    public class MvcApplication : System.Web.HttpApplication
    {
        public static BlogArticleRepository mainBlog; 

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            mainBlog = new BlogArticleRepository("TALK_ABOUT_PATH", "blog.dat");
        }
    }
}

The challenge is in understanding the path that we will send in which will allow us to get to the blog.dat file.

Understanding CurrentDirectory In A Web Application

The best way to get an idea of the path where the web application executes is to place a breakpoint at the top of the Application_Start() method and then execute some code in the Visual Studio Immediate window.

Once you place the breakpoint, you can press F5 and the application will start in Debug mode.

Once the application starts and lands on the breakpoint, you'll see the line highlight in Visual Studio.

At that point you can move to the Immediate Window and execute the following line of code:

System.IO.Directory.GetCurrentDirectory() <ENTER>

It'll look like the following:

immediate window

That is the path where IIS Express (Visual Studio's mini-web server) runs to host to your ASP.NET MVC application.

However, that is not the path where we want to load our blog.dat from.

We actually want to load our file from the location under our web site.  I've added a new folder to our application named blogFiles and dropped the blog.dat file in there.  

blogFiles folder

The Point of RootPath

We need the complete absolute path to that file.  Most likely, on my machine it will be different than yours, because my project directory is in a different location.  And, it will surely be different than what you have on your production web server.  That is why I allow you to send in the rootPath which will be used to determine where the file is located.  

Production Path Challenges

I've also found that when I'm developing on my local machine I need an easy way to switch that path back and forth since my production path is completely different.  I use GoDaddy hosting which hosts numerous web sites on the same server so they generate a path to your web site and you need to be able to send that one in dynamically.  That's why it is separate.

On my development machine the path to that file is : c:\Dev\WebDev\BasicMVC2\BasicMVC\blogFiles

You can see part of my path has "BasicMVC2" which is most likely different than yours.  I've been creating alternate versions as I've written this article.  

Using Real RootPath : Stepping Into Code

So now I've changed the code to point to the real path on my dev machine and I've started debug mode again with the breakpoint and stepped through code to prove that the blog.dat is loaded.  That all looks like the following:

blog.dat is loaded

Using Immediate Window To Verify Execution

You can see that I've executed a line of code in the Immediate window which references our new BlogArticleRepository.  The code I ran looks like:

mainBlog[0].Title <ENTER>

That in turn displays the value for the BlogArticle which is : Visual Studio's Greatest Hit's

Warning!! You Must Set RootPath in Global.asax.cs

The first time you run you have to set the RootPath value in the global.asax.cs since I cannot know what that value will be.  I've set the value to null and have wrapped a check for that value so it will throw an exception to warn you.  It will look like the following if you don't set it:

rootPath is null exception

Next Steps To Create Usable Blog

This is great success because now all we have to do is:

  1. Add a view to display our list of articles.
  2. Add a View to display the actual target article (VisStudio1.htm in this case)
  3. Add a way for the user to get to blog item (add a menu item).

Let's do all that work now.

Add New Menu Item

Let's flip our todo list upside down and first add a way to get to the blog content.  This will help refresh our memory on how we learned to do this in the part 1 of this article series.

  1. Go to the \Views\Shared folder in the BasicMVC project and open the _Layout.cshtml file.
  2. Add the new Blog menu item as the first menu item in NavBar by adding the bolded code below:
<div class="navbar-collapse collapse">
     <ul class="nav navbar-nav">
       <li class=@(@ViewBag.selectedItem == "blog" ? "active" : "")>@Html.ActionLink("Blog", "Index", "Blog")</li>
      <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>

That new list element will become a new NavBar item -- but remember it will not work yet.

Missing Controller and Action

Keep in mind that the ActionLink() method takes an Action (Controller method) and a Controller name to determine what route will match, which action will run and which View to display to the user.

Add BlogController

To fix this, let's go and add the BlogController now.

To do this (we learned in Part 1) you simply right-click the Controllers folder and choose the Add > Controller... menu item in Visual Studio.

add new controller

Next, we choose Add MVC5 Controller with read/write actions.

add controller step 2

Finally, we have to name our controller using the ASP.NET MVC convention which is <noun>Controller.  In our case it is BlogController.

add BlogController

Visual Studio will generate the new BlogController for us and open it for editing.

Go ahead and add the code to set the ViewBag.selectedItem so that the new Blog menu item will have it's style changed when it is selected (Learned In Part 1).

The code you want to add is bolded in the example snippet that follows:

using System.Web.Mvc;

namespace BasicMVC.Controllers
{
    public class BlogController : Controller
    {
        // GET: Blog
        public ActionResult Index()
        {
            ViewBag.selectedItem = "blog";
            return View();
        }

We can't quite test the changes we've made yet, because we need to add an associated View.

Let's do that now.

Add the Blog View

When we created our new BlogController Visual Studio anticipated that we would want a new View so it created a new folder named Blog under the Views folder.

blog folder

Right-click that folder and choose Add > View...  The following dialog box will appear: (as we saw in Part 1)

new view

Change the View name to Index and leave the rest the same and click the [Add] button.

Again, Visual Studio will generate the new View (Index.cshtml) and open it for editing.

Build the application and run it.  HINT: Visual Studio shortcut keys to build and run are CTRL-F5.

You will see that the new NavBar item has been added and the new View loads when it is clicked and the NavBar element changes styles when it is selected.

blog navbar item added

Now we are ready to get to the code which will allow us to really see something happen.

Let's move fast now so you can see this thing in action.

Move Scripts So We Can Use Them In Page

The first thing we want to do is make a small alteration to where we Render our scripts (we learned about Bundling in Part 1).  

Currently the _Layout.cshtml has them at them rendering (loading) after the rest of the page, but I need jQuery to already loaded up so I can manipulate the DOM. That means we want to simply move those lines from the bottom of _Layout.cshtml to the head section.   The final product will look like the following:

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

You'll find the lines which are bolded, near the end of the _Layout.cshtml file.  Cut them and move them up.

Next, let's alter our BlogController to alter our Index action so that it begins loading and using our list of blog articles.  Go ahead and change the code so it now looks like the following and then I'll explain what the code does.

BlogController Code

public ActionResult Index(int? articleId, bool? forceReload)
        {
            MvcApplication.mainBlog.GetAllBlogArticles(forceReload);
            ViewBag.Articles = (List<UnRio.Models.BlogArticle>)MvcApplication.mainBlog;
            // WARNING!!! Insure that ViewBag.BlogPath terminates with a slash /
            ViewBag.BlogPath = "../blogFiles/";
            if (articleId != null)
            {
                ViewBag.currentArticle = articleId;
            }
            return View();
        }

Nullable Types Help Out

First of all you can see that I've added two nullable parameters (articleId and forceReload) because they will not always be sent in on the URI. 

ArticleId Used to Load Specific Article

We will soon see code that handles if the articleId value is set, then it will load that article automatically so the user can read it instantly.  This allows you to give out URLs to your specific blog article in the form of http://BasicMVC.com/blog?articleId=5.

ForceReload Allows New Articles To Be Loaded

The forceReload boolean helps us so that if it is sent in and is true then we can reload all the articles from the blog.dat file.  If we didn't add an option like this, then the new articles would only load when the application is restarted.  That is true because we are loading these as a static application global resource in the global.asax.cs and that collection is only reloaded when the application starts (Application_Start()).

To make the articles reload you simply send in a blog URI which contains the forceReload set to true like the following:

http://BasicMVC.com/blog?forceReload=true

When you do that, the value will be evaulated inside the UnRio method GetAllBlogArticles and the method will call the LoadBlogArticlesFromDataStore() method which will actually read the blog.dat file again and reload the List<BlogArticle>.  Here's the code that calls the load method:

public void GetAllBlogArticles(bool? forceReload)
        {
            if (this.Count == 0 || (forceReload == true))
            {
                this.Clear();
                LoadBlogArticlesFromDataStore();
            }
        }
        

What's the Point of forceReload?

The real point is that when you add a new article entry in blog.dat and a new article, then all you have to do is load the URI (http://BasicMVC.com/blog?forceReload=true ) in your browser and the list will be updated and then all users will see that new article as the default article at the top of the list.   No need to restart your application or anything.

Back at the BlogController code you can see the next thing we do is set / create a new item in the dynamic ViewBag variable called Articles.  This is just a convenience variable which I will use in the view to iterate through the List<BlogArticle>.

ViewBag.Articles = (List<UnRio.Models.BlogArticle>)MvcApplication.mainBlog;

After that we set another convenience item in our ViewBag, which will help us build the path to the dynamic content of our target HTML files.

ViewBag.BlogPath = "../blogFiles/";

That value will make a bit more sense when we next look at the code will run in the View.

Finally, our BlogController also checks to see if the articleId is not null. If it isn't, then someone has sent a value on the queryString because they are loading an older article that they want to go to directly.  So in that case, we again set a convenience value in the ViewBag.  ViewBag is a real hoot, ain't it?  :)

if (articleId != null)
  {
    ViewBag.currentArticle = articleId;
  }

Blog.cshtml View : Much of the Work Goes On Here

Once we update our associated View (Blog.cshtml), this thing is going to start working.

Grab the final code from the download for Blog.cshtml and add it to your project, if you're working along.  Then, instead of just displaying all the code at once I'll display code blocks and describe exactly what they do.

Loads Articles But Not Complete Yet

Before I explain each code snippet, go ahead and build and run it so you can see what it looks like and how it loads our top (newest) article: VisStudio1.htm.  

Not quite complete

A Few Things Wrong

This may look correct, but there are still a couple of things wrong.

  1. The cursor is an I-bar when you hover over the article titles
  2. The article titles don't really stand out.
  3. The user cannot tell that the article titles are clickable -- I want the style to change on hover

We can change all of those items by updating the CSS.  Let's do that, get a final product running and then I'll walk you through the code blocks and explain exactly what blog.cshtml does so you can own it for yourself.

Alter CSS : Add Styles To Make View Active

Now, we are going to add some styles to our site which will make the rendering of our Blog page a little prettier and provide feedback to the user when she floats over the clickable links on the left.

In Part 1, we learned that the main styles for our ASP.NET MVC application are found in the Content folder in the site.css file.  Go ahead and open up that file and simply paste all of the following styles in.  The last item in that file should be the style we previously added : .navcustom  You can just copy the following styles after that item.

input,
select,
textarea {
    max-width: 280px;
}

.article:hover{
    background-color:#efae14;
    font-weight:bold;
}
.article{
    font-size:large;
}

.pageSection {
    margin-left:0px;
    padding-left: 0px;
    padding-right: 0px;
     margin: 0px ;
     background-color:aliceblue;
}
.leftcolumn, .rightcolumn {
    border: 1px solid white;
    float: left;
    min-height: 25%;
    color: black;
}

.leftcolumn {
    margin: 0;
    padding: 0;
    border: 0;
    cursor: pointer;
        /*background-color: #111;*/
}

.rightcolumn {
/*        width: 75%;*/
        background-color: lightyellow;
        
}

.tight{
    margin-top:20px;
    padding:0px;
}

h3 .tight{
    display: inline-block;
    padding:-5px;
    padding-top:8px;

}
.pubDate{
    font-size:x-small;
    
}

.minus-container{
    margin: 0;
    padding: 0;
    border: 0;
}

.leftPad{
    margin-left:20px;
}

Once you add those styles and rebuild, run and refresh the page you should see:

  1. A hand icon for the clickable link article titles when you hover over them
  2. Better (larger font) for the article titles to set them apart.
  3. Hover action over titles changes their color to indicate to user that the item is active (see next partial image).

mouse hover action

Code Explanation For View

Let's look at the code snippets and wrap this article up, and then you should be able to use UnRio in your own web applications very easily after this.

All of the View Code is found in /Blog/Index.cshtml.

We'll go top down through the file examing the code snippets.  The code snippets found in the page are a mixture of Razor, jQuery and some pure JavaScript.  These will provide good examples of how you can manipulate your Views into showing your data in your projects.

The first thing we see is the Razor script:

@{   ViewBag.Title = "RAD Dev US - Blog";

   Layout = "~/Views/Shared/_Layout.cshtml";
   ViewBag.selectedItem = "blog"; }

Here we are just setting the Title that appears on the Browser's title bar.   Then we set the Layout that is used for the page (it's the normal one).  Finally I set the selectedItem = "blog" as we saw in Part 1 to insure the Blog NavBar item is highlighted.

The next thing you see in /Blog/Index.cshtml is a jQuery script:

 <script>
(function () {
  $(".pubDate").remove();
  $(".article").remove();

}());

  </script>

Here, I do a jQuery selector to find the item with a pubDate class and an article class (CSS class) and then I simply call the jQuery method to remove those elements.  This insures that later when I append to those elements (when the page is loaded or refreshed) that I don't duplicate articles in the list on the left.

A bit further down we see the real meat of the work done in a Razor script.

 

foreach (var item in ViewBag.Articles)
    {
          <span class="pubDate">Published: @item.Created.ToString("yyyy-MM-dd")</span>
    <p class="article list-unstyled" id="article_id_@item.Id" onmousedown="showPreview('@ViewBag.BlogPath@item.RelativeFilePath','article_id_@item.Id')">
        @item.Title
    </p>

            }
            if (ViewBag.currentArticle != null)
            {
                List<UnRio.Models.BlogArticle> localArticles = (List<UnRio.Models.BlogArticle>)ViewBag.Articles;
                ViewBag.currentArticle = localArticles.Find(x => x.Id == ViewBag.currentArticle);
                if (ViewBag.currentArticle == null)
                {
                    // the id for the article wasn't valid so load the default;
                    ViewBag.currentArticle = @ViewBag.Articles[0];
                }
            }
            else
            {
                ViewBag.currentArticle = @ViewBag.Articles[0];
            }
        }

 

Dynamically Displaying the Article List

The first thing we do is iterate through the ViewBag.Articles.

As you can see, we build the article entries which appear on the left and we get the article titles and publish dates to present to the user.

Finally, you can see that if the ViewBag.currentArticle id matches we set it so it is the one that displays.  Otherwise we simply set the most recent article (first on listed in blog.dat) to render.

Finally, you'll see two JavaScript methods:

function showPreview(article,element) {
   $('.rightcolumn').load(article);
   if (element != null) {
     $(".article").css("background-color", "");
     $("#" + element).css("background-color", "lightgrey");
   }
 }
 function setSelectedArticle(articleId) {
   $("#" + "article_id_" + articleId).css("background-color", "lightgrey");
 }

showPreview JavaScript Uses jQuery Asynchronous Call

The showPreview() JavaScript function is the really interesting one. When the user clicks one of the items in the article list, I call jQuery load() method to asynchronously load the associated HTML file (VisStudio1.htm for example) in the target div (.rightColumn).

That's all there is to it.

Now, you can extend this code even more.

Next Article

I will soon write up another article for people who simply want to use the UnRio library and add quick blog pages to their site.  That article will detail the quick steps to using it and setting it up on their own ASP.NET MVC web sites.  

Thanks for reading my article.

History

First version of article and code: 01/23/2015

License

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

Share

About the Author

raddevus
Software Developer (Senior) RADDev Publishing
United States United States
Roger has worked in IT for over 25 years in numerous roles (Technical Support, Quality Assurance, Capacity & Performance Engineering and Software Development).
During that time, he has recognized that software often just becomes another layer of work that the user has to wade through.
Sometimes technical documentation is like that too: so confusing and complex that it wastes developers' time.
That's why when he writes his books like Programming Windows 10 Via UWP and his articles (Practical Electronics For Makers) he strives to explain things in the shortest available space with the simplest language possible. Often that means, writing in a tutorial style with numerous images to help guide the user.
He believes the best guiding principle is Einstein's famous quote: "Everything should be made as simple as possible, but not simpler."

Comments and Discussions

 
QuestionSuggestion Pin
amar mishra22-Feb-18 2:00
Memberamar mishra22-Feb-18 2:00 
Questionproblems with the interface Pin
Member 1283936417-Nov-16 22:24
MemberMember 1283936417-Nov-16 22:24 
AnswerRe: problems with the interface Pin
raddevus18-Nov-16 3:32
communityengineerraddevus18-Nov-16 3:32 
QuestionmainBlog object not being recognized. Pin
Eleanor Anderson2-Feb-16 4:25
MemberEleanor Anderson2-Feb-16 4:25 
AnswerRe: mainBlog object not being recognized. Pin
raddevus2-Feb-16 4:29
communityengineerraddevus2-Feb-16 4:29 
GeneralRe: mainBlog object not being recognized. Pin
Eleanor Anderson2-Feb-16 6:55
MemberEleanor Anderson2-Feb-16 6:55 
QuestionGlobal.asax.cs Pin
Bob Kaye28-Jan-16 9:25
MemberBob Kaye28-Jan-16 9:25 
AnswerRe: Global.asax.cs Pin
raddevus28-Jan-16 9:47
communityengineerraddevus28-Jan-16 9:47 
GeneralRe: Global.asax.cs Pin
Bob Kaye28-Jan-16 10:59
MemberBob Kaye28-Jan-16 10:59 
AnswerRe: Global.asax.cs Pin
raddevus28-Jan-16 11:28
communityengineerraddevus28-Jan-16 11:28 
GeneralRe: Global.asax.cs Pin
Bob Kaye28-Jan-16 12:21
MemberBob Kaye28-Jan-16 12:21 
AnswerRe: Global.asax.cs Pin
raddevus28-Jan-16 11:57
communityengineerraddevus28-Jan-16 11:57 
GeneralRe: Global.asax.cs Pin
Bob Kaye29-Jan-16 1:37
MemberBob Kaye29-Jan-16 1:37 
GeneralRe: Global.asax.cs Pin
Bob Kaye29-Jan-16 6:39
MemberBob Kaye29-Jan-16 6:39 
GeneralMy vote of 5 Pin
Santhakumar M24-Jan-16 6:49
professionalSanthakumar M24-Jan-16 6:49 
GeneralRe: My vote of 5 Pin
raddevus28-Jan-16 9:46
communityengineerraddevus28-Jan-16 9:46 
GeneralRe: My vote of 5 Pin
Santhakumar M28-Jan-16 20:11
professionalSanthakumar M28-Jan-16 20:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Article
Posted 23 Jan 2016

Stats

31.1K views
1.5K downloads
28 bookmarked