From the Blog Clippings Category
The Microsoft Architects Journal 4 is now available
here as a pdf. The table of contents lists these articles.
- Choosing the Right Presentation Layer Architecture
- Information Bridge Framework
- Benchmarking a Transaction Engine
- Enterprise Architecture Alignment Heuristics
- Razorbills
- Next Generation Tools for OOD
I've been ever so slowly adding new .Net 2.0 features to the Virtual Cellar
code. The most apparent changes are driven by the use of ASP.Net 2.0 features,
most notably the GridView control and the new suite of DataSource controls.
I wasn't too happy to see the introduction of the SqlDataSource control, I
thought it just encouraged bad layering practices, allowing the population of
the new Data Controls through straight ahead SQL statements. Sure, I could setup
a stored procedure and call that with the SqlDataSource control, but I was still
programming to the database. It just felt wrong.
So, I was rather dejected, I really wanted to use the new GridView control in
my application. That's when I found out about the ObjectDataSource control.
There's a great
MSDNTV Episode that talks about this. This was the perfect solution. I would
be able to use my Domain Objects directly with the GridView control. There was
only one problem, the object used as the data source needed to have a default
contructor.
As you may (or may not) remember, I based the Virtual Cellar model on the
Repository Pattern. Unfortunately, I based my domain objects on a base class,
RepositoryItemBase, that does not allow for a default constructor, instead it
includes a reference to the RepositoryFactory, should any of the classes such as
the Wine class need to expose properties of another aggregate root (Producer).
Part of this was to get around the problem of having a reference to the
ProducerRepository in the Wine class, instead a request would be made to the
RepositoryFactory to generate a Factory instance (in this case a ProducerFactory)
for re-hydrating the Producer class from the ProducerRepository, from
information stored in the Wine class.
The short answer, is that I am unable to use the ProducerRepository as an
ObjectDataSource, because it does not support a parameterless default
constructor. So my immediate fix is to create an adapter class
ProducerDataSource that wraps the functionality of the ProducerRepository, yet
has a parameterless default constructor to satisfy the requirements of the
ObjectDataSource.
Here's a shot of the class diagram modeled in the new VS2005 diagram tool.

As you can see, I've defined only one method "SelectByName" for the purpose
of my testing. The method takes a string that is used for matching on the
Producer.Name field. It simply calls the QueryByName method in the repository,
which maps to the GetByNameAsDataReader in the IProducerProvider interface. This
example is using the OleDbProducerProvider for the purposes of acting on an
OleDb data source.
I've used another 2.0 feature (Generics) to return a IList<Producer> from the
ProducerDataSource.SelectByName method. The GridView can now take this IList<Producer>
and map it to grid columns.
Here's a quick code excerpt that illustrates the ProducerDataSource object
and the ProducerGridView interaction.
<form id="form1" runat="server">
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" />
<asp:GridView ID="ProducerGridView" runat="server" DataSourceID="ProducerDataSource" AutoGenerateColumns="False">
<Columns>
<asp:BoundField HeaderText="Id" DataField="Id" SortExpression="Id"></asp:BoundField>
<asp:BoundField HeaderText="Name" DataField="Name" SortExpression="Name"></asp:BoundField>
<asp:BoundField HeaderText="Address" DataField="Address" SortExpression="Address"></asp:BoundField>
<asp:BoundField HeaderText="City" DataField="City" SortExpression="City"></asp:BoundField>
<asp:BoundField HeaderText="State" DataField="State" SortExpression="State"></asp:BoundField>
<asp:BoundField HeaderText="Country" DataField="Country" SortExpression="Country"></asp:BoundField>
<asp:BoundField HeaderText="PostalCode" DataField="PostalCode" SortExpression="PostalCode"></asp:BoundField>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProducerDataSource" runat="server" TypeName="Lorengo.VirtualCellar.Business.ProducerDataSource"
SelectMethod="SelectByName">
<SelectParameters>
<asp:ControlParameter Name="name" ControlID="TextBox1" PropertyName="Text" DefaultValue="Robert Mondavi"
Type="String" />
</SelectParameters>
</asp:ObjectDataSource>
</form>
|
You'll notice that the ObjectDataSource has a SelectMethod attribute which
maps to the SelectByName method on my ProducerDataSource. Also the <SelectParameters>
node maps the TextBox1 controls Text property to the "name" parameter of the
method. This allows the user to enter a value in the text box to search for.
The resulting pages looks like this

Unfortunately, the page does the query when it is loaded, so the DefaultValue
attribute of "Robert Mondavi" is used and displayed. What I would like to do is
prevent the initial lookup from occurring, presenting the user with just a
search box and button. Does anybody know of hand how to accomplish this?
In the meantime, I'm going to revisit my Repository / DataSource classes and
see if I can't come up with a better solution. Now that I know there is an easy
way to utilize my business objects with the data controls, I'm excited.
I've begun creating the website that will house the Virtual Cellar data model
and form the main user interface for the application. My next couple of entries
will pertain to some initial tasks that need to be done so that I start hanging
pages on the website. In this entry I'll discuss the setup of the site master
template for the Virtual Cellar.
The General Layout
I plan on having a three column layout along with a header section, as
illustrated in the picture below.

There are four major sections
- Banner
The Header section will contain the application title bar as well as the
main menu navigation for the application
- ContextBar
The ContextBar will contain information that will vary depending on the
context of the application. For example, if the user is not logged in, it
will contain a username, password prompt. If the user is logged in, it could
contain statistics about her account, an overview of her cellar statistics
or latest headlines via rss feeds.
- Main
The Main section will be where the user spends most of her time interacting
with the application. The content of the section will be the data pulled
from the Virtual Cellar catalog in the form of reports or where the user
will enter new information into the Virtual Cellar.
- SideBar
The sidebar section is where items of interest will be displayed depending
on the type of information being displayed in the main section. These could
be Google AdSense links, or links to items for sale on Amazon and eBay.
Creating The MasterPage
In Visual Studio, I create a new MasterPage template by Right-Clicking on the
web project and select to add a New Item. I'm then presented with the following
dialog box.

After adding the VirtualCellar.master file to the project, I'll go ahead and
create the following <div> tags that define each of the sections.
<body>
<form id="MainForm" runat="server">
<div id="Banner">Banner
</div>
<div id="ContextBar">ContextBar
</div>
<div id="Main">Main
</div>
<div id="SideBar">SideBar
</div>
</form>
</body> |
The next step is to add the <style> section to arrange the <div> sections in
the order above
<head>
<style type="text/css">
body {
margin:10px 10px 0px 10px;
padding:0px;
}
#Banner {
background:#fff;
height:70px;
border-top:1px solid #000;
border-right:1px solid #000;
border-left:1px solid #000;
voice-family: "\"}\"";
voice-family: inherit;
height:69px;
}
html>body #Banner {
height:69px;
}
#Banner p {
font-size:14px;
padding:10px 10px 0px 10px;
margin:0px;
}
#ContextBar {
position: absolute;
left:10px;
top:80px;
width:200px;
background:#fff;
border:1px solid #000;
}
#Main {
background:#fff;
margin-left: 199px;
margin-right:199px;
border:1px solid #000;
voice-family: "\"}\"";
voice-family: inherit;
margin-left: 201px;
margin-right:201px;
}
html>body #Main {
margin-left: 201px;
margin-right:201px;
}
#SideBar {
position: absolute;
right:10px;
top:80px;
width:200px;
background:#fff;
border:1px solid #000;
}
</style>
</head> |
You may notice the use of the infamous
"voice family" hack, this is
to get around the various browser bugs or interpretations of the css box model.
This code also allows us to view our layout semantically. For the longest time I
did layout using tables, little did I know that was a major crime according to
the css folk. This article on
retooling slashdot with
css got me hooked on using css for layout. Another great site is the
CSSZenGarden, but I digress. The above
css code will give us the nice layout we set out to construct.
Creating a New Page Based on The Master
Now that I have the VirtualCellar.master page created, I can begin using it
in new pages that I create. So I'll right click on my web project and select Add
New Item. I'm present with the same dialog box as before, but this time I
choose, Web Form. I also check the box that says Select Master Page. After
selecting Add, a listbox containing all of the defined MasterPages are shown,
and I select VirtualCellar.master. A new file Default.aspx is created that
contains the following code.
<%@ Page Language="C#"
MasterPageFile="~/VirtualCellar.master"
CodeFile="Default.aspx.cs"
Inherits="Default_aspx"
Title="Untitled Page"
%> |
And the output looks like this!

Next time I'll look at adding a menu to the application using the new <asp:Menu
/> and <asp:SiteMapDataSource /> controls
1.1
Setting Up The December Team System Preview
I've recently downloaded the Microsoft Visual Studio Team
System December CTP from MSDN, and have begun the process of setting up the
full blown system. I’m using a Dell PowerEdge 2550 Dual P3-1Ghz system with 2GB
of memory running Virtual Server 2005. The plan is to setup 2 virtual machines
running Windows Server 2003 each having 640 Mb of memory.
Here’s how it will break down
Ø
Hercules: The Dell rack server configured with Window Server
2003, running Virtual Server 2005, DNS, and Active Directory for the
“LanThrash” domain.
Ø
Hades: The first Virtual Server that will function as the “Data
Tier” for the Visual Studio Team System.
Ø
Hermes: The second Virtual Server that will function as the
“Application Tier” for the Visual Studio Team System.
I'll be following the instructions found here http://go.microsoft.com/fwlink/?LinkId=40042&clcid=0x40
1.1.1
Configuring Hercules for VSTS
Not much needs to be done since Hercules is already setup as
the Domain Controller for the LanThrash domain.
1.1.1.1 Create New
Domain Users in Active Directory on Hercules
Start/Administrative Tools/Active Directory Users and
Computers/Domain/Users/New/User
Add TFSSetup
Add TFSService
1.1.2
Configuring Hades for the Data Tier
1.1.2.1 Add New
Domain Users to Local Administrator Group on Hades
Start/Administrative Tools/Computer Management/Local Users
and Groups/Groups/Administrators/Add to Group...
Add LanThrash/TFSSetup
Add LanThrash/TFSService
1.1.2.2 Install
IIS 6.0
Start/Adminstrative Tools/Manage Your Server/Add or Remove a
Role
Add Application Server Role
Enable ASP.Net
1.1.2.3 Install
Microsoft SQL Server Beta 2
Download Microsoft SQL Server Beta 2 from msdn subscriptions
Use the Virtual Server 2005 Administration website to mount
the .iso file to the Hades CD/DVD Virtual Drive
Run the Install Program
Follow the instructions "How to: Install Microsoft SQL
Server 2005 for the Team Foundation Data Tier" in the setup guide
Reboot the server
Finish installation of SQL following the "How to:"
1.1.2.4 Install
VSTS Data Tier on Hades
Logon to Hades with the TFSSetup user
Run the Data Tier Setup program following the prompts.
(Note: Apparently
you can’t mount an .iso file larger than 2.2Gb under Virtual Server, so I
used the Virtual
CD-ROM Control Panel to mount the .iso file on Hercules, and then copy the
/VSTS/DT folder to Hades directly. Apparently you cannot share a mounted .iso
either, the other work around was to add the mounted drive on Hercules as a
resource to the Hermes machine, but I couldn’t get that to work on Virtual
Server)
1.1.3
Configure Hermes for the Application Tier
1.1.3.1 Add New
Domain Users to Administrators group on Hermes
Same as Hades
1.1.3.2 Install IIS
6.0
Same as Hades
1.1.3.3 Install
Windows SharePoint Services
Download and run Windows
SharePoint Services with SP1
Choose the Typical Install
1.1.3.4 Logon to
Hermes under the LanThrash/TFSSetup user
1.1.3.5 Run the
Setup program according to the directions
It should be noted that I had a couple of problems while
doing the install. First this
one, while trying to find the Data Tier databases, but it went
away, for whatever reason. The next one was an Error 3200, which someone
else reported
here, I simply hit Retry and it worked, although another solution or cause was
having a website running on the same port 8080, that Team System was attempting
to use.
1.2
Conclusion
All in all it went rather smoothly, of course this was over
a period of a couple of days as I had to configure my new domain, and all my
other miscellaneous client computer, etc. I’ll now perform the straight ahead
installation of the Client Tier on my Dell Optiplex, but that should be easy J
Well, I got fed up with Qwest charging me over $50 a month
for my local & long distance service, so I signed up for Vonage VOIP on
December 7th of last year. I’m now giving my one month update.
First let’s investigate my Qwest bill
|
Feature
|
Qwest
|
Vonage
|
|
Basic Residence Line
|
12.50
|
24.95
|
|
Federal Access Charge
|
5.94
|
0.00
|
|
Regulatory Recovery Fee
|
|
1.50
|
|
Non Published Service
|
.75
|
|
|
Voice Messaging
|
6.95
|
|
|
Total
|
26.14
|
26.49
|
So a quick look shows the two to be about equal. But now let’s
figure in the local long distance, and the other long distance
|
Feature
|
Qwest
|
Vonage
|
|
Local Long Distance (Avg Charges)
|
6.76
|
|
|
Long Distance Charges (Avg Charges)
|
4.60
|
|
|
Total
|
11.36
|
0.00
|
Hmm, so I can save on average about 10 bucks a month by
going with Vonage. Now, here is where the real advantage comes in. Let’s
compare the traditional phone company and VOIP on the “other charges”
spreadsheet. The Qwest bill says to look at www.qwest.com
for charge explanations. The closest I found (I didn’t look too hard) is in the
table below.
|
Qwest Charges (Explanation
Here)
|
Qwest
|
Vonage
|
|
Federal Excise Tax @ 3%
|
.84
|
0.75
|
|
State Sales Tax @ 6.5%
|
.47
|
|
|
Local Sales Tax @ 1.9%
|
.14
|
|
|
Special District Sales Tax @ 0.4%
|
.03
|
|
|
City Occupation Tax @6.382%
|
1.72
|
|
|
State 911 @ .20 / line
|
.20
|
|
|
Local 911 @ .50 / line
|
.50
|
|
|
Federal Universal Service Fund @ 8.9%
|
.53
|
|
|
TRS Excise Funds Federal ADA @ .14 / line
|
.14
|
|
|
Telephone Assistance Program @ .13 / line
|
.13
|
|
|
Total
|
4.70
|
0.75
|
Now let’s look at AT&T’s charges