Developing Blogo.NET – The Business Layer
With the database and Data Access Layer in place, it is now time to move on to the Business Layer. As suggested earlier, the purpose of the Business Layer is to provide operations to the View layer. It makes use of the Data Access layer to communicate with the database.
Whilst developing the Data Access layer, we already implemented part of the Business Layer, being the Business Objects. These Business Objects are essentially the glue between the Business and Data Access layer. The second part to implement in the Business Object layer is the Business Object Managers.
A Business Object manager simply manages instances of Business Objects. The operations that the Business Object Managers must support depend greatly on the business logic of your application. At the very minimum, they must support the same operations as defined in the Data Access layer:
GetItem – returns a Business Object to the View
GetList – returns a list of Business Objects to the View
Save – Saves a Business Object from the View to the database
Delete – Deletes a Business Object from the database.
Note that the Business Object Managers do not interact with the database directly; instead they will make use of the operations we defined in the Data Access layer earlier. This makes the implementation of the Business Object Managers very easy: it’s only a matter of making calls to the Data Access layer. Let’s have a look at the implementation of CommentManager, the Business Object Manager for comments, which is located in the file “Comment.cs” in the Code/Business folder.
The Count method makes a call to the Data Access layer (CommentDB) to retrieve the number of comments in the database.
The GetList method makes a call to the Data Access layer to retrieve a list of Comment Business Objects. Notice how the method is marked with a DataObjectMethod attribute. This attribute marks the method as a data operation. This attribute is not mandatory, but makes working with the ObjectDataSource in the View layer much easier.
I will not enlist the other methods in this file, as they are all the same: they make simple calls to the Data Access methods we defined in the Data Access layer earlier. It may seem pointless to define these Business Object Managers if they do not have their own logic, but this is in fact the place where you would implement business logic such as security, workflow, logging, etc. Furthermore, the Business layer enables us to decouple the View layer from the Data Access layer: if we ever want to replace the data source, we only have to modify the Data Access layer, and not the View layer.
At this point in time, it is time to test the Data Access and Business layer. This can be done using a method of your choice: manually, or via test scripts (automated unit tests).
Good news: We are done implementing the backend of our application. It may appear as a lot of work, but once you get the hang of it, you can build it very fast. We will see that our effort pays off when we build the View layer; with a properly designed back-end, creating the pages becomes child’s play. Before we start working on the View layer, let us summarize what we have in the back-end:
Figure 1: Blogo.NET class diagram of back-end

For each entity, we have four classes. Let’s take the blog entity as an example:
- BlogEntryManager: This class manages instances of BlogEntry Business Objects.
- BlogEntry: “Dumb” Business Object to hold properties
- BlogEntryDB: Data Object for blog entries
- blogentry(not displayed in diagram): This is the LINQ data object for blog entries, as defined in the mapping file.
As we will build the View layer, we will see that we will only interact with the Business Object Managers, the rest is abstracted away from us.
Developing Blogo.NET – The View Layer
Finally, we can get around to building something visual. There are many approaches to build the View layer; this is the one that I followed:
- Find a nice template. I simply used an open source web site design and applied it to my project.
- Create master pages to implement the reusable elements of the web site design.
- Build the user-facing pages.
- Build the admin pages.
Web site templates
For this project I had no interest in hand-crafting a new web site design. Instead, I simply used one of the open source web site designs available as oswd.org. The one I used can be found here. The raw template looks like this:
Figure 2: Blogo’s pick of open source web site design.

The site’s design seems suitable for a blog application, as it is narrow, has two columns and a chronological display of entries.
Page architecture
The next step to perform is to convert the open source template, which is delivered as HTML, CSS, and JavaScript, into master pages. For this we need to imagine how our content will fit into the design. With a bit of sketching, we can conclude the following:
- Things like the background, header and footer will need to be displayed on every page. This kind of content will have to be placed at the site-level master page.
- User-facing pages will inherit the elements from the site-level master page, but will have specific content for both content columns. The right column will have a fixed set of navigation options, whilst the left column (main content column) will be different per page.
- Admin-facing pages will inherit the elements from the site-level master page, but will have specific content for both content columns. This content will be different from the user-facing pages, in that the right side column will have a fixed number of admin options, and the left column content will be different per admin page.
This means that we will create three master pages, one at site-level, one for the user-facing pages that will inherit from the site-level master page, and one for the admin-pages that will also inherit from the site-level master page. All pages that we create will inherit from either the Page master page (user-facing) or the Admin master page, except for these two exceptions:
- The error page will inherit directly from the site –level master page.
- The login page will inherit directly from the site-level master page.
This leads to the following page architecture:
Figure 3: Blogo.NET page architecture.

See Figure 3. Site.Master is the site-level master page. All pages in the site inherit from this page, either directly or indirectly. Site.Master defines two ContentPlaceHolders, one for each column.
The Page.Master and Admin.Master pages are nested master pages; they inherit from the Site.master master page. Both master pages apply to the right column that was inherited from Site.Master. For Page.Master, the right column is used to display various blog navigation options (i.e. by tag, month, articles, and feeds). For Admin.Master, the right column is used to display various admin navigation options (i.e. manage blog entries, log, setup, etc).
All user-facing pages will inherit from Page.Master. At this point in the inheritance chain, only the left column (content) can be adjusted in the new page, as all the rest is inherited. Exceptions within the domain of user pages are the error page and login page, these need no navigation options, therefore they directly inherit from the site-level master page.
All admin pages will inherit from Admin.Master. At this point in the inheritance chain, only the left column (content) can be adjusted in the new page, as all the rest is inherited.
Note:
Next to the master page inheritance, Blogo.NET also makes use of a base page. Each user-facing page’s code behind file inherits from this base page (located in View/Masters/_PageBase.cs). The PageBase class makes UI formatting functions (i.e. ImplodeTags) available to all pages inheriting from PageBase.
With the above page architecture in place, it becomes incredibly easy to create new, good-looking, consistent web pages very quickly. Note that as of Visual Studio 2008, nested master pages display well inside the Designer, making it easy to see what the end result will look like when you are working on a page.
The process I followed to implement the Site master page is as follow:
- Analyze the web site design you have downloaded. Two specific things to check for are: What does the file structure look like? On what CSS, JS and image files does the design depend? Within the main HTML file, where do the first and second columns begin and end?
- Import the CSS, JS and image folders required to make the design work into your Visual Studio solution. In the Blogo.NET solution, these elements can be found in the View/CSS and View/Images folders. It is recommended to keep the directory structure the same as in the original design.
- Create a new master page element inside your solution, and name it Site.Master. Next, paste the full content of the main HTML file of your design inside the new master page, just below the first line.
- Inside the new master page, locate the column begin and end tags, and remove the content inside them. Next, place ContentHolders in each column and give them an appropriate name.
- Check your master page in Designer mode to see if it renders correctly. If not, you may have to update the references to the CSS and image files.
Below is a fragment of Blogo.NET’s site master page that indicates where the ContentPlaceHolders are positioned:
The process described above takes care of the static markup creation of the site-level master page. However, we want at least one part to be dynamic: the header menu. The header menu is a site-level navigation bar located just below the header graphic. In Blogo.NET, the source of the menu entries is the application’s sitemap file, Web.sitemap. By default, it looks like this:
It is typically up to administrators to maintain the menu entries in this file. To retrieve and display the links in the header menu properly, we make use of the new ListView control and a SiteMapDataSource control. The code fragment below, as taken from the Site.Master file realizes this:
Note that you can find the Blogo.NET master pages in the View/Masters folder of the solution.
At this point of development, we are probably more interested in getting a user-facing page up and running than an admin page. Therefore, let us first start by creating the Page.Master master page, the basis for all user-facing pages.
What we want in all our user-facing web pages is a consistent navigation sidebar, which in case of the Blogo.NET design, is located in the right column. This navigation sidebar will list the following:
- A small description of the blog
- A list of tag links. This list will only show tags for which there is at least one blog entry. Clicking on a tag takes the user to all blog entries of that tag.
- A list of article links. This list will show the title of blog entries marked as “article”. Upon clicking the title, that specific blog entry (article) is opened.
- A list of year-month links, sorted descending. This list will show the months in which a blog entry was posted. Upon clicking a month, all blog entries posted in that month are displayed.
- A list of RSS feeds to which the user can subscribe
This sidebar will appear on all user-facing pages; therefore we will implement it in the Page.Master master page. The first element of the sidebar, the blog description, is in fact a custom setting in the web.config file of the application:
The blog description field is in fact an application configuration parameter that is maintained by the blog administrator from the blog setup page (discussed later). Blogo.NET contains a utility class (Code/Utils/BlogoSettings.cs) that allows you to read/write these settings from/to the web.config file. Since there is always only one instance of these configuration parameters, they are not stored in the database, but in the web.config file.
In the right column of the Page.Master file, a label control is placed that during Page_Load is filled with the value of the blog description, as taken from the web.config file using the BlogoSettings class:
Next to implement in the sidebar are three blocks of links, all generated from database content. There are many ways to implement this, but an attractive and desired choice in our architecture is to use ASP.NET’s new ListView control, together with an ObjectDataSourceControl. The ListView control gives us fine-grained control over the markup output, whilst the ObjectDataSourceControl enables us to data-bind the ListView to our Business Layer.
I will demonstrate the implementation process for the first block (tag links), the other two work very similar and can be inspected in detail from the source code of the Page.Master file.
First, create an ObjectDataSource control on the Page.Master file and use the smart tag menu to configure it. In the “Choose a Business Object” selection screen, select the TagManager class from the Business layer, and leave the checkbox “Show only data components” enabled.
Figure 4: ObjectDataSource Business Object picker

In the “Define Data Methods” screen, select the GetListUsedTags method for the SELECT statement.
Figure 5: ObjectDataSource data method picker

Note that the methods from our Business layer appear here because they are decorated with special attributes (discussed earlier). The GetListUsedTags method is a method from the Business layer that returns a list of Tag objects for which there is at least one blog entry. Since we only want to display this list of tags, we do not need to configure the UPDATE, INSERT, or DELETE data methods. Therefore, we can click on Finish to close the configuration wizard.
Next, we create a ListView control on the Page.Master file. It is important to set the following two properties:
DataSourceID: We need to set this to the ID of the ObjectDataSource control we just created.
ItemPlaceHolderID: We will set this to itemContainer.
Now that we have configured the ObjectDataSource and ListView controls, we can use the ListView’s markup templates to control what to output. This is typically a mix of static markup and dynamic data-bound content:
In this case we are using three different markup templates from the ListView control:
- LayoutTemplate: This part renders the top level nesting of the markup, it contains start and end markup. More importantly, in between is the
itemContainer PlaceHolder control, which will contain the resulting markup as produced by the ItemTemplate.
- ItemTemplate: This defines the markup that needs to be produced for each individual tag. As you can see, in this case it is a combination of static HTML, combined with data-bound tag properties (
id and tagname) from the Tag object.
- EmptyDataTemplate. This is what gets rendered when there are no Tag objects returned by the ObjectDataSource control.
The dynamic list of links in the sidebar for articles and blog entries by month work in a similar way: both use ListView and ObjectDataSource controls to configure what to retrieve and how to display it.
The last part of the sidebar is a list of feeds to which the user can subscribe. This list is static, and therefore can be implemented using simple markup in the Page.Master file:
Note:
By marking the <a href> tags to run at the server, we can use the ~ notation to conveniently link the root of our web application.
This completes the implementation of the Page.Master page. You may have noticed that we have linked to several .ASPX pages that we have not created yet. No worries, we will discuss these later.
We are now fully equipped to build our first user-facing page. You will see that our previous efforts will enable us to develop these very fast. Thanks to our master page architecture, every new user-facing page we build is a matter of filling the content column with the content we need using standard ASP.NET controls, all the rest is rendered in a consistent way automatically. If we would now create a new .aspx page and set it to inherit from the Page.Master file, it will look like this in the Visual Studio designer:
Figure 6: A new user-facing page in Design mode

As you can see, all nested elements are greyed out, enabling us to focus on the only column we can change: the content column.
Upon inspecting the requirements, we can conclude that the majority of the user-facing pages will be lists of blog entries, sorted by publication date (default), tag, year-month combination and articles. Although the sorting and filtering may be different per overview, the display of a single blog entry in such a list is likely to be the same across all these pages. Instead of repeating the markup and controls to render a blog entry across pages, we should really apply one of the most important design principles: DRY (Don’t Repeat Yourself).
A convenient way to reuse related markup and controls in ASP.NET is to create a web user control. In Blogo.NET, the web user control “BlogList.ascx” is located in the View/Controls folder of the solution. The control consists of three elements:
- A ListView. The ListView defines the markup of the blog entry list
- A DataPager. The DataPager controls the pagination of blog entries in the ListView
- An event. The code-behind file of the control contains a stub method
ImplodeTags, which calls the “real” ImplodeTags function from the base page of the current page. This method is required due to the limitations of data-binding complex objects within ASP.NET.
The ObjectDataSource control is not part of the web user control, since that is in fact the part that will greatly differ per overview of blog entries. The ListView inside the web user control instead implicitly links to an ObjectDataSourceControl named “ObjectDataSourceBlogs”.
With the reusable web user control in place, we can now start by creating the homepage. The process is as follow:
- Create a new ASPX page, name it “Home.aspx”. (In Blogo.NET located in the View/Pages folder)
- Set the master page property of the new page to point to the Page.Master file.
- Remove all content below the Page tag and insert the contentplaceholder tags. We will put our content in between them
- Include a label control inside the contentplaceholder tags, this label will be set during Page_Load with the value of the application configuration parameter “blog title” , which can be maintained by the blog administrator, and is stored in the web.config.
- Drag the BlogList web user control inside the contentplaceholder
- Add an ObjectDataSource control and name it “ObjectDataSourceBlogs”. Configure it to use the GetList method of the BlogEntryManager class in the Business Layer. Be sure to enable pagination for the ObjectDataSourceControl, as we only want to display the last three blog entries on the homepage:
EnablePaging: True
SelectCountMethod="Count"
StartRowIndexParameterName="StartRow" (querystring parameter “page”)
MaximumRowsParameterName="PageSize" (3)
Done. The source code of the Home.aspx file is as follow:
Thanks to our reusable BlogList control and master page inheritance, there are only a few lines of markup, and most of it is the result of configuration, not coding. The process explained above works similar for the creation of the other blog overview pages:
- BlogArticles.aspx. This page list all blog entries that are marked as type “article”.
- BlogByMonth.aspx. This page list all blog entries by a specified month.
- BlogByTag.aspx. This page list all blog entries by a specified tag.
The only thing different in each page is the configuration of the ObjectDataSource (selecting the correct GetList overload from the Business Layer, and the filter parameters, often taken from a querystring value, and possibly the header label. Therefore, I will not explain those pages, but encourage you to inspect them yourself in the View/Pages folder.
Next to the blog overview pages, there are a number of other pages that I will hereby briefly describe:
BlogEntry.aspx
This page displays a specific blog entry or article, based on the ID specified in the querystring. The page uses a ListView and ObjectDataSource to display the blog entry. Since a single blog entry can be seen as a list of length 1, the ListView is suitable for this. Furthermore, this enables us to reuse much of the markup from our BlogList web user control. Since we are only displaying a single blog entry on this page at all times, pagination is disabled.
Next on the page is a another ListViewControl and ObjectDataSource control which is associated with the CommentManager class from our Business layer. As input parameter the querystring ID to uniquely identify the blog entry is used, so that only comments associated with the blog entry are retrieved and displayed.
Finally, a “new comment” form is displayed, enabling user to post new comments to the blog entry. This form is build using standard ASP.NET web controls, being TextBox controls, Button controls, and RequiredFieldValidator controls to enforce validation of the fields. The new comment form is enclosed in a PlaceHolder control. This enables us to enable/disable it at runtime. This is required because blog administrators can decide per blog entry whether to allow comments or not. The Page_Load event contains code to dynamically show/hide the new comment form using the PlaceHolder control’s Visible value.
Of special interest is the code in the code-behind file that is associated with the click event of the Submit button of the comment form. Up until now, we have been using standard ASP.NET controls to bind with our Business Layer. In this case however, we are explicitly making use of our Business layer to save new comments to the database:
Note how with just a few lines of code, we have inserted a new comment in the database, using our previously defined Business layer.
File.aspx
The File page is a bit of a special case. Its purpose is to display the binary content of a file, indicated by the ID passed in the querystring. Therefore, we need to intervene with the standard HTTP response object of ASP.NET, set its MIME type, and then show the binary data (i.e. image data). In the Page_Load event of File.aspx, the following code takes care of this:
Once again we can see that there is great benefit in having a solid Business layer. Thanks to our FileManager we can implement a relatively complex feature with just a few lines of code.
TagCloud.aspx
The TagCloud page lists tags links for tags that are used in the blog, and sizes these links based upon the number of blog entries in each tag. There is no standard ASP.NET control to do such a thing; therefore it has been implemented as follow:
- The page contains a Label control.
- The
Page_Load event of the code-behind file contains the logic to render the tag cloud. This is done using a combination of the TagManager from the Business layer, and some calculation formulas to distribute the weight of the tags.
- The stylesheet View/CSS/default.css contains predefined tag sizing elements that determine the font-size for each scale.
Summary
In the second part of this series on the making of Blogo.NET we discussed the Business Layer and the View Layer. Then, we talked about the page architecture and showed how some of the pages of Blogo.NET are organized. In the next article we will talk about the Administration module, creating blog entries and security.
Other Parts
About Ferdy Christant
 |
"I am a software engineer and architect from the Netherlands. I've started out with Lotus Notes development in 1999 and have since then developed and certified myself in PHP, J2EE and .NET. In my free time, I blog and have a small open source web site for my projects. Furthermore, I enjoy m...
This author has published 3 articles on DotNetSlackers. View other articles or the complete profile here.
|
You might also be interested in the following related blog posts
The RTM SDKs Will Be Downloadable on November 28th, 2006
read more
Tag Those Posts About KB Articles, Methods and Properties
read more
Tag Those Posts About KB Articles, Methods and Properties
read more
EOAST - Evolution of a software thingy - Part 1
read more
|
|
Please login to rate or to leave a comment.