Start With The Database
There are many ways to start a project like this, but for me, the easiest was to begin by designing the tables that would capture the data I already knew I'd need. I did not expect this design to be final, but I had a good idea of what I wanted, and creating the data design first facilitated creating the program using the tools that ASP.NET provides. Thus, I started with a simple database design, as illustrated in Figure 1.
Figure 1. A simple database design
As you can see, each Bug is represented by a single entry in the Bug table and one or more entries in the BugHistories table. The entries in the BugHistories table serve as an audit trail for each time the bug is modified. The information captured is the time the modification is made (or the bug is created) in the TimeStamp field, who modified the bug, and both a ShortDescription (to be shown in the grid of bugs) and a LongDescription (to provide extensive information). Other information captured is the current severity (one of the values stored in the Severities table) and the current status (again, a value in the Statuses table), along with Notes (additional information about the bug or about fixing the bug) and the current owner.
Design Choice: Of course, I could have combined the Bug and BugHistories tables into one, but breaking them apart has a few advantages. First, the database will ensure that each bug has a unique ID (by making the BugID an identity column). Second, if it turns out there is immutable information about a bug (if, for example, we decide that the ShortDescription should never change) that data can be moved from BugHistories to Bugs, making the relationship crystal clear.
Both the Owner and the ModifiedBy fields are populated by values stored in the Users table of the ASPNETDB.MDF database (Figure 2) created by the Web Site Administration Tool (WAT).
Figure 2. The Users table of the ASPNETDB.MDF database
Design Choice - I have intentionally denormalized the BugHistories table, using the string version of the UserName rather than the UserID. This makes the coding easier without much cost, although I'm open to changing it (but not just to keep the purists happy).
Using the WAT
In phase 2, we'll create pages in the application itself to create new users and assign them to roles (if you're in a rush, see my early article on personalization), but for now letting the WAT do the heavy lifting makes a lot of sense. We get all the structure we need without having to write any code (see Figure 3).
Figure 3. Using the WAT
By using the WAT we can also configure roles for Customers, Developers, Managers, and QA, the four essential roles we'll use in phase 1 (see Figure 4).
Figure 4. Configuring roles with the WAT
Now that we've used the WAT to seed the Users table with a few names and assign them to roles, we're ready to create bugs and review their history. To do so, we'll create just three pages: TBTWelcome, which will provide the login to identify the current user, TBTReportBug to provide a form to report (or update) a bug, and TBTReview to see a list of the bugs. Further, to provide a uniform look and feel, all three of these will be contained within a Master page (TBT.master) which provides a small menu and a copyright notice, as shown in Figure 5.
Figure 5. The Master Page
All three pages will be contained within the ContentPlaceHolder, which allows them to share the banner, menu, and copyright, illustrated in Figure 6.
Figure 6. The Content Page