A basic practice in software development of all types is to use mechanisms that allow us to write and maintain code in a single place no matter how many difference places that code is used throughout our entire application.

When we’re building web sites, and more specifically web pages, the reuse of UI code can be especially challenging as the nature of web applications are stateless and in most models there is a 1-to-1 relationship between endpoints and “files”.

In ASP.NET WebForms we have master pages.

In Microsoft WebMatrix we have Layout Templates.

One of the advantages of the general move towards “standards based” web development is that HTML, CSS, and JavaScript can generally be used across different web development platforms and the technique described below can be used no matter which ASP.NET Development model you choose. (WebForms, ASP.NET MVC, WebMatrix)

I’ll use WebMatrix for the example.

Given a WebMatrix site created using the default “Starter” template the following Home Page and About Page can be displayed when the project is run.

Note that only the text inside the white area of the pages is different in the Default.cshtml and About.cshtml pages.

The Default.cshtml page contains only the following.

  1. {
  2. Layout = “~/_SiteLayout.cshtml”;
  3. Page.Title = “Welcome to my Web Site!”;
  4. }
  5. <p>
  6. ASP.NET Web Pages make it easy to build powerful .NET based applications for the web.
  7. </p>
  • Lines #1 & #4 are code delimiters.
  • Line #2 specifies a cshtml layout page to use.
  • Line #3 sets the value of a global variable to be used inside the _SiteLayout.cshtml template.
  • Lines #5 thru #7 are standard html markup.

The _SiteLayout.cshtml page contains all the markup that will be common across the multiple pages that will use this layout.

  1. <!DOCTYPE html>
  2. <html lang=”en”>
  3. <head>
  4. <meta charset=”utf-8″>
  5. <title>My ASP.NET Web Page – @Page.Title</title>
  6. <link href=”@Href(“~/Styles/Site.css”) rel=”stylesheet” />
  7. <link href=”@Href(“~/favicon.ico”) rel=”shortcut icon” type=”image/x-icon” />
  8. </head>
  9. <body>
  10. <div id=”page”>
  11. <
    div id=”header”>
  12. <p class=”site-title”>My ASP.NET Web Page</p>
  13. <div id=”login”>
  14. @if (WebSecurity.IsAuthenticated) {
  15. <p>
  16. Welcome <a href=”@Href(“~/Account/ChangePassword”) title=”Change password”>@WebSecurity.CurrentUserName</a>!
  17. <a href=”@Href(“~/Account/Logout”)“>Logout</a>
  18. </p>
  19. } else {
  20. <ul>
  21. <li><a href=”@Href(“~/Account/Register”)“>Register</a></li>
  22. <li><a href=”@Href(“~/Account/Login”)“>Login</a></li>
  23. </ul>
  24. }
  25. </div>
  26. <ul id=”menu”>
  27. <li><a href=”@Href(“~/”)“>Home</a></li>
  28. <li><a href=”@Href(“~/About”)“>About</a></li>
  29. </ul>
  30. </div>
  31. <div id=”main”>
  32. <div id=”content”>
  33. <h1>@Page.Title</h1>
  34. @RenderBody()
  35. </div>
  36. <div id=”footer”>
  37. &copy; @DateTime.Now.Year – My ASP.NET Web Page
  38. </div>
  39. </div>
  40. </div>
  41. </body>
  42. </html>

Note especially:

  • Lines #5 & #33 where the Page.Title variable set in the Default.cshtml page is used by the template.
  • Line #34 – the call to RenderBoby() where the content of the page that uses the template is inserted.

This is a very simple and useful construct for code reuse, but does requires some special considerations when context specific presentation is required such as when a navigation menu is included in the site template.

For example, given the User Interface Design below:

Note the top page menu.

The items in the menu are static for all pages but the STATE of the menu items is specific to the site’s navigational “context”.

Note the image above is of the “Home” page (Default.cshtml) and the “Home” menu item is highlighted or “active”.

The template itself contains all the menu items, but each page will be required to set it’s corresponding menu item to an active state when the page is loaded.

Our layout template defines the page menu as follows.

  1. <div id=”topnav”>
  2. <ul>
  3. <li id=”Home”><a href=”Default.cshtml”>Home</a></li>
  4. <li id=”Style-Demo”><a href=”Style-Demo.cshtml”>Style Demo</a></li>
  5. <li id=”Full-Width”><a href=”Full-Width.cshtml”>Full Width</a></li>
  6. <li><a href=”#”>DropDown</a>
  7. <ul>
  8. <li><a href=”#”>Link 1</a></li>
  9. <li><a href=”#”>Link 2</a></li>
  10. <li><a href=”#”>Link 3</a></li>
  11. </ul>
  12. </li>
  13. <li class=”last”><a href=”#”>A Long Link Text</a></li>
  14. </ul>
  15. </div>

The CSS of the navigation container is as follows. (See the nav.css file)

  1. #topnav{
  2. display:block;
  3. float:right;
  4. margin:7px 0 0 0;
  5. padding:0;
  6. list-style:none;
  7. font-size:14px;
  8. font-weight:bold;
  9. font-family:Verdana, Arial, Helvetica, sans-serif;
  10. }

And the actual items as follows.

  1. #topnav li li a:link, #topnav li li a:visited{
  2. width:150px;
  3. float:none;
  4. margin:0;
  5. padding:7px 10px;
  6. font-size:12px;
  7. font-weight:normal;
  8. }

The “hover” and “active” states are implemented in the following CSS definition.

  1. #topnav li a:hover, #topnav ul li.active a{
  2. color:#FFFFFF;
  3. background-color:#B2C629;
  4. }

Enter a tiny bit of jQuery code.

You will notice that the _SiteLayout.cshtml page contains the following line to pull the jQuery library into our pages.

  1. <script type=”text/javascript” src=”scripts/jquery-1.4.4.min.js”></script>

Note that I’m pulling the jQuery library in from a static location. This is fine for development but in production you may benefit greatly from using the Microsoft CDN [ Read more HERE. ]

Having done this, each individual page that uses our _SiteLayout.cshtml page can include a bit of jQuery / JavaScript code like this.

  1. <script>
  2. $(document).ready(function () {
  3. $(“#Home”).addClass(“active”);
  4. });
  5. </script>

If you have never used jQuery before I suggest you have a look at this quick introduction [ See HERE ]

What the bit of code above does is define a JavaScript function to be run wen the page DOM is fully loaded.

Note that our _SiteLayout.cshtml page has an <li> item named “Home”. This is the “Home” Menu Item.

  1. <li id=”Home”><a href=”Default.cshtml”>Home</a></li>

Then this call…..

  1. $(“#Home”).addClass(“active”);

… “selects” the DOM element who’s id = “Home”, and the .addClass method applies the “active” css class to the “Home” element.

In this way, these 5 lines of JavaScript in the “Home” page sets the “Home” menu item to “active”.

We then add a similar bit of code to each .cshtml page that needs to set it’s corresponding menu item to active (in the Layout Template.)

Since JavaScript is incredibly flexible, we could use variables and move the actual addClass call to the Layout file, but it’s likely that we will have addition DOM manipulation to implement in our pages so, I prefer the pattern of implementing $(document).Ready() in the page itself.

I hope someone finds this useful.

Stay tuned, more WebMatrix and jQuery UI / ASP.NET work coming.