skmFAQs.NET: An ASP.NET FAQ Application

 

Scott Mitchell
4GuysFromRolla.com

May 2005

Summary: This article provides an overview of skmFAQs.NET, an open-source ASP.NET 1.x Frequently Asked Questions (FAQ) application. (15 printed pages)

Introduction

As the Internet and World Wide Web have become more ubiquitous and more accessible to non-computer–savvy individuals, a variety of Web applications have sprung up to enable various forms of communication. One of the most popular of these is the blog (or weblog), which provides an easy means for an individual to publish to the Internet. Another popular communication application is the Wiki, which establishes a sort of virtual whiteboard on the Internet to which anyone can contribute.

The goal of these and similar technologies is to enable two parties to communicate with one another and they can be categorized by the plurality of the parties involved in the communication. There are three possible senders or receivers:

  1. An individual
  2. A defined group
  3. Everyone / anyone

Different applications allow for different pairings of these types of pluralities. For example, e-mail and instant messaging provides individual-to-individual communications, or with e-mail listservs or chatrooms, individual to a defined group communications. Most blogs enable communication from an individual to any visitor, although a blog could be configured to allow access only to a defined group (for example, an internal blog on a company's intranet). Wikis, on the other hand, are designed to allow communication flow from anyone to everyone.

A communication model that is a marriage of the blog and the Wiki models is one that allows a defined group to communicate with anyone. This is similar to a Wiki in that a number of individuals can contribute, but unlike a Wiki, it places restrictions on who can contribute and, possibly, how they can do so. Large Web sites, particularly those with a large amount of content, typically use Content Management System (CMS) software to provide this mode of communication. CMS software, though, is often very expensive and often contains a gaggle of features that are needed only for sites with an abundance of content that is published and updated often. Such software is oftentimes overkill for a not-for-profit company or club. These smaller users might have a public-facing Web site that they want to allow a number of employees or members to maintain, rather than forcing such responsibilities on a sole person, but don't need the power of a professional CMS system.

There already exist excellent, open-source Web applications for ASP.NET for these products. In the blog arena, there's Community Server; for Wikis, see FlexWiki; DotNetNuke and Rainbow are ASP.NET CMS projects. However there is still a niche for a Web application that allows for communications originating from a defined group to anyone. To address this need I started an open-source Web application called skmFAQs.NET. The high-level goal of skmFAQs.NET is to make it easy for anyone to add and integrate a Frequently Asked Questions (FAQ) section to their Web site, one that could be updated by a predefined set of users.

In this article we'll examine the design goals for skmFAQs.NET and explore how its architecture helped realize these goals. We'll also run through a quick tour of skmFAQs.NET's features and step through the setup and installation process. Before delving into the design goals of skmFAQs.NET, let's first take a look at a case study of ASPFAQs.com, an ASP and ASP.NET FAQ Web site. Such an examination will highlight some of the challenges and required features of any real-world Web application that intends to allow a defined group of users to publish information online.

ASPFAQs.com: A Case Study

As the author of numerous ASP and ASP.NET books, magazine articles, and online articles, I receive a torrent of technical questions in my Inbox each day. While each problem posed had its own twists, there were many commonly asked questions—so many, in fact, that in September 2000 I decided to launch ASPFAQs.com to serve as a public repository of answers for some of the most frequently asked questions.

Initially, ASPFAQs.com simply acted as a front end for a database of FAQs and their answers. The database began with only two tables: a Categories table and a FAQs table, with the latter storing a record for each FAQ, its answer, and the category to which it belonged. When I wanted to add a new FAQ, I'd visit a particular Web page that would allow me to enter the question, specify the category, and provide the answer.

This worked well enough when there was only a sole contributor, but soon regulars at ASPMessageboard.com were interested in posting answers to frequently asked messageboard questions. These contributors started by e-mailing me the questions and answers that I would then insert via the Web interface. Furthermore, I was the go-to contact when one of these contributors wanted to refine their efforts by adding to or editing their answer.

Eventually ASPFAQs.com morphed into a more mature application, one that had logins for the contributors so that they could add and edit FAQs without my intervention. This added a new table to the database schema, Users, which had a record for each user account in the system. Each user account was given a specific access level from one of the following three possible options:

  1. Administrator—an administrator could create or remove user accounts and FAQ categories, and create, edit, or delete any FAQ.
  2. Trusted Contributor—contributors who had a track record of posting engaging, error-free FAQs were given trusted contributor access. When a trusted contributor created a new FAQ it appeared on the Web site immediately.
  3. Untrusted Contributor—when a new user was added to the system they'd come in at this level. An untrusted contributor's new FAQs are not shown on the site until they have been approved by an Administrator. This allowed me a chance to review and possibly modify the content before going live with it.

I marked my own user account as the sole administrator account and then doled out trusted contributor and untrusted contributor statuses to the other users based upon their previous track record.

Despite ASPFAQs.com's evolution over the years, creating a new FAQ is still a rather esoteric act, as ASPFAQs.com's Web interface accepts the answer in a particular markup that's a subset of HTML. This means that the contributors must learn this markup in order to have finer control over the formatting of their postings. This is a similar problem experienced by many Wiki engine users as well.

In retrospect, ASPFAQs.com did a number of things well, but it also left a lot of room for improvement. Some of its achievements include:

  • Enabling multiple contributors to easily create and edit their own FAQs, without any intervention needed by yours truly.
  • Providing different levels of access rights, although in review the access levels were not fine-grained enough (see the next section).

The main areas for improvement include:

  • An improved data entry experience. Rather than forcing the contributors to memorize the ASPFAQs.com syntax, it would have been more user friendly to have opted to allow input using a rich text editor, such as FreeTextBox.
  • Finer-grained control over access rights. I found that there needed to be an access right level somewhere between Administrator and Trusted Contributor, thereby allowing a highly trusted user to be able to edit or approve others' FAQs, but still not have full administrative rights. Furthermore, with ASPFAQs.com access rights are global to all FAQ categories. Ideally access rights could be assigned to user accounts on a category-by-category basis.
  • Inability for contributors to add on to one another's FAQs. With ASPFAQs.com, contributors could only edit FAQs they had created. If contributor A wrote a FAQ and contributor B had a great code sample or explanation that she wanted to tack on, she'd have to e-mail her addition to contributor A, who would then have to go into the system and append the addendum.
  • Lack of a sound architecture. ASPFAQs.com was not created with much forethought given to its architectural design. The end result is that extending ASPFAQs.com is not easy. Adding a new FAQ category, for example, requires manually going through a Web interface; there's no API to create one programmatically, short of calling the appropriate stored procedure. Additionally, duplicating any sort of functionality found in ASPFAQs.com on another site or on another part of the same site would require a replication of code and database calls.
  • A flat category model. While ASPFAQs.com could support an arbitrary number of categories, there was no means to establish a hierarchy between them. (For example, it was not possible to create a "Security" category with subcategories such as "Forms Authentication," "Encryption," and "Authorization.")

Armed with the real-world experience of creating and maintaining ASPFAQs.com, I felt confident in drafting the design goals for skmFAQs.NET.

The Design Goals of skmFAQs.NET

When creating an application, I typically go through an iterative process when formulating the design goals. I start by formulating a small handful of very high-level goals. Once these have been crafted, pondered over, and accepted, I then break these high-level goals into more specific objectives. This process may continue through several iterations until I have a number of very concrete tasks at hand.

When creating skmFAQs.NET I decided that it would strive to meet three high-level goals:

  1. Ease of use,
  2. Allow for varying levels of permissions and rights for the members publishing FAQs on a category-by-category basis, and
  3. Make the application highly extensible and customizable.

Armed with the three high-level goals listed above, the next step was to break out these goals into more concrete objectives.

Making skmFAQs.NET Easy to Use

I started my process with the "Make sure skmFAQs.NET is easy to use" goal, writing down ideas on how to accomplish this end. There are two different types of skmFAQs.NET users: content creators and page developers. Content creators are those users that interact with the application through the Web site interface, adding new FAQs to the site. Page developers, on the other hand, are the users that have to incorporate skmFAQs.NET into an existing Web application, or who need to customize the functionality or appearance of skmFAQs.NET. Clearly the objectives for making skmFAQs.NET easy to use are wildly different for these two classes of users.

Some brainstorming led to specific objectives for both classes of users, some of which bleed into accomplishing the other two high-level goals. The goals for users adding FAQs through the Web interface include:

  • Adding a FAQ should be as simple as using a word processor. No knowledge of a special markup language—even HTML—should be required on the user's part.
  • Appending content to an existing FAQ should be a trivial task and not require the original contributor to take any special action.
  • Administrative tasks—adding new users, approving FAQs, editing/deleting others' FAQs, etc. —should be simple and straightforward and all doable through a Web interface.

Some of these more specific objectives may seem so intuitive that they're not worth listing. I have found, however, that it helps to enumerate even the blindingly obvious goals and tasks, in part because they can help discover features that might not have otherwise been realized. For example, drilling further into the second goal listed above will force me to critically think about what features will make appending content to another's' FAQ a truly effortless task. Additionally, listing even the apparent requirements provides a complete scope, which helps, in turn, with establishing time estimates, setting milestones, and evaluating progress.

The more detailed objectives for page developer users include:

  • The ability to use the Web-based functionality through a programmatic API.
  • Encapsulation of common user interface functionality in custom ASP.NET server controls.
  • An easy and quick installation and setup process.

Since the purpose of this article is an overview of skmFAQs.NET and not an in-depth functional specification document, let's not bother drilling down into these usability objectives any further. As we examine skmFAQs.NET in more detail throughout the remainder of this article you'll see features and design decisions that help accomplish these goals.

Allowing for Fine-Grained Access Rights

Based on my experience with ASPFAQs.com, I wanted to provide a much finer level of control over access rights in skmFAQs.NET. In designing the system I wanted to allow for a use case in which a large site could use a single instance of the skmFAQs.NET application to set up multiple, independent FAQ sections.

For example, consider a site like Darren Neimke's Project Distributor. Project Distributor is a Web site that serves as a repository for small code projects. Users can create an account on Project Distributor and host their applications there. With such a Web application it would be useful to allow each user to have a FAQ for his software projects. Each user's FAQ section would be separate from other users in every possible sense:

  • User A could not edit or add FAQs to User B's FAQ section (unless explicitly given access rights).
  • When viewing User A's FAQ section, only User A's FAQs would be shown, and not User B's, User C's, etc.

To enable scenarios like this, access rights were implemented on a category-by-category basis. To implement a system like this, each project on Project Distributor would have a FAQ category created for it with the applicable User receiving the necessary rights. (This could be achieved programmatically when a new user account was created in the system using the skmFAQs.NET API.)

Deciding the granularity of the entities in the system to which rights apply is only half of the puzzle; the other half is to specify what set of permissions can be applied to each entity. There are a variety of permissions that could be applied to a category, including the ability to:

  • Create FAQ entries.
  • Edit your own FAQ entries.
  • Edit all FAQs.
  • Delete your own FAQs.
  • Delete others' FAQs.
  • Approve or reject pending FAQs.
  • Move your own FAQs to another category.
  • Move others' FAQs to another category.
  • Create, edit, and delete subcategories.

At one extreme these permissions could be set for each user for each category. A less verbose scheme would group related permissions into roles, and allow roles only to be assigned on a per-user, per-category basis. The two extremes represent a classic tradeoff between expressiveness and usability; since one of my main design goals for skmFAQs.NET was ease of use, I decided to opt for the role-based approach. The system consequently has four predefined roles:

  • Administrator—the administrator role is applied on an application-wide basis (and not on a category-by-category basis). Users marked as administrators have full rights to all FAQs in all categories and can create, edit, and delete user accounts.
  • FAQ Editor—a FAQ editor is akin to a category-specific administrator. FAQ Editors can approve, create, edit, and delete any FAQ within the category.
  • Trusted Contributor—as with ASPFAQs.com, a trusted contributor can create, edit, and delete their own FAQs, but not others. Also, when they create a FAQ it immediately appears on the site.
  • Untrusted Contributor—again, as with ASPFAQs.com, an untrusted contributor can create, edit, and delete their own FAQs, but when creating a new FAQ it must first be approved by a FAQ Editor or Administrator before appearing on the site.

Figure 1 shows a screen shot of the skmFAQs.NET Permissions Administration page, which is accessible only to administrators. From this screen, the administrator can select a user from the drop-down list and then specify roles for any of the categories in the system.

ms972972.skmfaqs01(en-us,MSDN.10).gif

Figure 1. Permissions administration

Architecting an Extensible and Customizable Application

Of the three high-level design goals the most emphasis was placed on the third and final one: ensuring that skmFAQs.NET was extensible and customizable. In my past experiences working with pre-built commercial Web applications I've endured much frustration and pain trying to tweak rather rigid applications to fit my particular requirements. To provide an application that could meet the unique demands of different customers I focused on the following two objectives:

  • Provide a straightforward programmatic API that provides a powerful interface into the system, yet encapsulates the complexity.
  • Utilize the provider model design pattern at the data access layer, thereby allowing an enterprising page developer the option to swap out the backend data store without requiring any additional changes.

The architecture for skmFAQs.NET was modeled after the architecture used by the Community Server forums (the forum software that powers the ASP.NET Forums) and consists of four layers:

  1. The Presentation Layer, which comprises the ASP.NET pages of the application along with custom, compiled ASP.NET server controls that encapsulate common functionality in a Web control.
  2. The Application Logic Layer, or API, which consists of a handful of classes for programmatically working with the FAQ application.
  3. An Abstract Data Access Layer, which provides the methods that interact with the backend data store. The Data Access Layer simply defines the methods and properties of the DAL; to actually interact with a backend data store, there needs to be a provider class that extends and actually implements the abstract DAL. skmFAQs.NET ships with such a concrete provider that utilizes Microsoft SQL Server 2000 and later; developers can craft providers of their own to plug into the system in order to have skmFAQs.NET utilize a different backing store (such as Microsoft Access, XML files, Oracle, or others).
  4. The Data Store, either a database, XML file, or other.

Figure 2 shows a graphical representation of the skmFAQs.NET architecture.

ms972972.skmfaqs02(en-us,MSDN.10).gif

Figure 2. skmFAQs architecture

The Presentation Layer's ASP.NET pages contain the vital pages for the FAQ application's functionality. There are two classes of pages: pages that all users can visit, such as those that show a listing of FAQ categories and display a particular FAQ; and those that only registered users can view, which include pages for adding and editing FAQs, creating user accounts and setting permissions, and so forth. skmFAQs.NET also ships with a number of compiled, custom server controls to ease the burden of the page developer. For example, to display a FAQ on a page simply drop a ShowFAQ Web control on the page and set its FAQID property to the ID of the FAQ to display. Figure 3 shows the ShowFAQ Web control through the Visual Studio .NET Design tab; you can customize the formatting through the control's stylistic properties (BackColor, ForeColor, Font, AnswerStyle, QuestionStyle, and so on) and very specifically tailor the rendered markup, if desired, through the QuestionTemplate and AnswerTemplate templates.

ms972972.skmfaqs03(en-us,MSDN.10).gif

Figure 3. ShowFAQ Web control at design time

The Application Logic Layer contains the application's programmatic API. All of the pages and controls in the Presentation Layer communicate directly with the Application Logic Layer (as opposed to accessing the database directly). The Application Logic Layer partitions the API into related classes—CategoryAPI, FAQAPI, PermissionAPI, and so on—that contain static methods. Additionally, there is a set of business objects, which are classes that abstractly define the logical entities in the system. These business objects are the abstractions that are used in communications between the Presentation Layer and Application Logic Layer. For example, there exists a Category class that contains the properties that are inherent to a FAQ category (CategoryID, Name, Description, etc.). Many of the CategoryAPI methods, such as AddCategory(Category), accept and/or return Category instances.

The Abstract Data Access Layer is implemented as an abstract class, defining numerous abstract methods that a concrete derived provider must implement. Additionally, the Abstract Data Access Layer provides actual, implemented methods for those tasks common to all providers, such as populating instances of the business objects. skmFAQs.NET ships with a built-in provider, SqlDataProvider, that fills the role of a concrete provider by interacting with Microsoft SQL Server as its backing store.

Note The provider model design pattern is used frequently in ASP.NET 2.0. If you are not familiar with this design pattern, I recommend reading Rob Howard's Provider Model Design Pattern and Specification two-part article series on the provider model design pattern and how to implement it in ASP.NET 1.x: Part 1 and Part 2.

Installing and Setting Up skmFAQs.NET

skmFAQs.NET can be installed on any Web server that supports ASP.NET 1.x. As mentioned earlier, skmFAQs.NET comes with a data provider for Microsoft SQL Server databases, so it is recommended that your site can connect to a SQL Server database. If you do not have SQL Server at your disposal you could create a data provider to utilize a different data store (Microsoft Access, XML files, etc.). Assuming your site meets the technical requirements, installing and setting up skmFAQs.NET can be done in a matter of minutes.

Before you can begin installing skmFAQs.NET you'll first need to visit the skmFAQs.NET Download Page. The download includes:

  1. SQL scripts to create the database's tables, stored procedures, views, UDFs, and initial data.
  2. The complete C# source code for the skmFAQs.NET application.
  3. A demo Web site that can be used as-is or tailored to meet your unique needs.

Upon downloading skmFAQs.NET, the first step is setting up the database, which involves running the supplied SQL scripts. These SQL scripts not only create the necessary tables, views, stored procedures, and so on, but also populate the tables with some initial data. In particular, a single user account is created with the username Admin and password admin. This combination should be changed as soon as possible, either during pre-installation, by changing the username/password in the SQL script, or later, through SQL Enterprise Manager or through the demo Web site's Administration pages.

Once the database elements have been created and populated with initial data, the next step is to push the demo Web site up to your Web server: If you're moving the site to a remote server simply use FTP or the Copy Web Site feature in Visual Studio .NET; if you're developing locally, just configure IIS to create a new virtual directory pointing to the location of the unzipped demo Web site. The demo Web site's Web.config file contains a <skmFaqSettings> element (shown below) that needs to be updated to include information pertinent to your database server and Web site.

  
    <skmFaqSettings 
defaultProvider="SQL" 
   showCategoryUrl="~/ShowCategory.aspx?ID={0}" 
   showFAQUrl="~/ShowFAQ.aspx?ID={0}"
   siteTitle="skmFAQs.NET"
   adminEmail="CHANGE@ME.COM"
>


<!-- Set the connectionString property to the 
     connection string to the database where you ran the
     included SQL scripts and have created the skmFAQs.NET 
     database elements...

     For databaseOwner, put the name of the owner of the 
     database elements.  Typically this will be the
     username with which you connected to the database server 
     to run the SQL scripts... -->
<providers>
   <add name="SQL"
        type="FAQComponents.Provider.SqlDataProvider, FAQComponents"
        connectionString="PUT YOUR CONNECTION STRING HERE"
        databaseOwner="dbo" />
</providers>
</skmFaqSettings>

  

In the <skmFaqSettings> section, update the siteTitle and adminEmail attribute values to reflect your Web site's title, time zone, and your e-mail address. The showCategoryUrl and showFAQUrl attributes specify the paths to the ASP.NET pages responsible for showing a category's FAQs and showing a particular FAQ, respectively. The demo Web site uses the page names ShowCategory.aspx and ShowFAQ.aspx, so when using the demo Web site, leave these settings as-is. However, if you need to customize skmFAQs.NET and want to use different pages for displaying categories or FAQs, update the page URLs here. The defaultProvider attribute specifies what provider from the <providers> section should be used.

The <providers> child element contains details for the data provider(s) available, along with details pertinent to the provider. By default, skmFAQs.NET ships with one provider, named SQL, which provides connectivity to a Microsoft SQL Server database. In the <add> element the details for the SQL provider are spelled out, including the type of the provider (Namespace.ClassName, AssemblyName), the connectionString, and the databaseOwner. You will, of course, need to update the connectionString property with your database's connection string.

For more information on the skmFAQs.NET setup process, refer to http://skmfaqs.net/skmfaqs/ShowFAQ.aspx?ID=5.

Getting Started with skmFAQs.NET

Once the <skmFaqSettings> section has been configured, you should be able to visit the FAQ demo Web site. The site won't be too exciting, however, since there are no FAQs in the system. However, you can create a new FAQ by going to the Administration pages that are in the Admin subdirectory of the demo Web site (for example, if you installed the demo site at the virtual directory FAQs on your computer then the Administration pages would be at https://localhost/FAQs/Admin). Figure 4 shows a screenshot of the Administration page main menu.

Note When logging into the Administration pages you'll be prompted for your username and password. When setting up the initial data for skmFAQs.NET an account with the username Admin and password admin was created.

ms972972.skmfaqs04(en-us,MSDN.10).gif

Figure 4: Administration page

As Figure 4 shows, there are various options for Administrators, FAQ Editors, and Contributors. Since I have logged in as the Administrator, I can see all of these options; however, a FAQ Editor would see only the FAQ Editor and Contributor options, while a Contributor would only see the Contributor option.

The Administrator options include:

  • User Administration, which permits creating, editing, and deleting user accounts, as well as assigning category-by-category permissions.
  • Category Administration, which entails creating, editing, and deleting categories.
  • E-mail Template Administration, for tailoring the e-mails that users receive based on events. For example, when an Untrusted Contributor submits a new FAQ, it must first be approved by an Administrator or FAQ Editor before it will appear on the site. Whether the FAQ is approved or rejected, the Contributor will receive an e-mail detailing what action was taken. The e-mail contents for this and other e-mail types can be tailored through the E-mail Template Administration page.
  • Reports, which show how many times a FAQ or category has been viewed in a given month. The Reports screen uses the free WebChart control created by Carlos Aguilar Mares.

The FAQ Editor options, which are available to both FAQ Editors and Administrators, include:

  • FAQ Moderation, which allows for pending FAQ submissions from Untrusted Contributors to be approved or rejected.
  • FAQ Maintenance, which allows for updating, deleting, or moving FAQs others have written. An administrator can update or delete any FAQ in any category. A FAQ Editor can only update or delete others' FAQs in categories for which he is a FAQ Editor.

Contributors—both trusted and untrusted—have only one option at their disposal: FAQ Administration. The FAQ Administration screen allows users to create, edit, or delete their own FAQs. Contributors and FAQ Editors can only create FAQs in those categories that they have rights to; Administrators can create FAQs in any category in the system.

One of the lessons learned from ASPFAQs.com was to make creating FAQs as easy as possible. Ideally, the user should not be required to know a special syntax, such as HTML or the Wiki keywords. I decided to utilize John Dyer'sFreeTextBox control, which provides a rich, WYSIWYG text editor. Figure 5 shows a screen shot of the creation of a new FAQ:

ms972972.skmfaqs05(en-us,MSDN.10).gif

Figure 5. Creating a new FAQ

A FAQ in skmFAQs.NET is composed of a question along with one or more FAQ parts. A FAQ part is part of the answer. When creating a new FAQ, the supplied answer is the first FAQ part. However, other contributors might want to add to the answer of a FAQ. When viewing a FAQ, logged-in users will see a Contribute to this FAQ's Answer link at the bottom of the FAQ. Clicking on this will take them to a page where they can provide an additional FAQ part to the FAQ. (This link will appear only if the user has permissions to create FAQs in the FAQ's category; Untrusted Contributors' FAQ additions do not appear until approved by an Administrator or FAQ Editor.)

Conclusion

This article provides a case study of ASPFAQs.com, followed by an overview of skmFAQs.NET, an ASP.NET 1.x application for allowing a defined group of individuals to publish information online. skmFAQs.NET is geared toward maintaining lists of frequently asked questions, a requirement for many Web sites. skmFAQs.NET was designed to be both easy to use as well as extensible.

The most up-to-date information on skmFAQs.NET is available on the official Web site, http://skmFAQs.NET.

Happy Programming!

Before submitting my article to my MSDN editor I have a handful of volunteers help proofread the article and provide feedback on the article's content, grammar, and direction. Primary contributors to the review process for this article include Atif Aziz, Carl Lambrecht, Julius Estrada, Jeffrey Palermo, Hilton Giesenow, and Milan Negovan. If you are interested in joining the ever-growing list of reviewers, drop me a line at mitchell@4guysfromrolla.com.

 

About the author

Scott Mitchell, author of six books and founder of 4GuysFromRolla.com, has been working with Microsoft Web technologies for the past five years. Scott works as an independent consultant, trainer, and writer. You can reach him at mitchell@4guysfromrolla.com or via his blog, http://ScottOnWriting.NET.

© Microsoft Corporation. All rights reserved.