open source comments suggest edit

This is part 1 in a three-part series on copyright law and open source licensing. After this, continue onto Part 2 and Part 3 of the series.


Cover As is customary when a non-lawyer attempts to discuss the finer points of the law, I must start with a disclaimer. I know some fine lawyers, but I, sir, am not a lawyer. So please do not consider this to be legal advice. It is merely a rough primer on copyright law as it pertains to software based on my readings and conversations. If you need specific legal advice, talk to your own damn lawyer.


After finishing the Fogel book, “Producing Open Source Software”, I followed up by reading “Understanding Open Source and Free Software Licensing” by Andrew M. St. Laurent.

This book combined with previous readings serves as the inspiration and source for this series. I will focus on the issues pertinent to software developers who wish to get involved in open source development. For a more complete treatment of the topics, I recommend reading the books mentioned.

In this first post in this series, I will discuss the basics of copyright law. This will set the stage for part 2 in which I will discuss software licensing.

In countries that support the Berne Convention, as soon as you set pen to paper, brush to canvas, or fingers to that dirty keyboard, the work you create is automatically afforded protection by copyright law. This assumes that your creation is not itself infringing on another’s copyright such as plagiarism. Also, there must be a small degree of creativity in the work. For example, you cannot simply jot down and copyright names copied from a phone book. Additional copyright protection is available through registration with the copyright office, but registration is not required.

Note that copyright applies to a particular expression of an idea, not to the idea itself. You can copyright a specific drawing of a penguin, but your copyright does not apply to drawings of penguins in general. Trademarks and patents are used to provide legal protections for concepts, ideas, facts outside of the scope of copyright law, but that is a topic out of scope for this post.

So exactly what rights do you have to copyrighted works? Well the obvious right is the right to copy. A copyright gives the owner full and exclusive rights to control who may copy or create a derivative of a work and how that may be done. As a copyright owner, you may state that nobody is allowed to copy or make derivative versions of your work (though the doctrine of “fair use” allows some non-infringing uses such as quoting from the work in a book review). A copyright gives the owner exclusive rights to a work, but this protection does not last forever.

If someone were to infringe on your copyright, you have the right to sue for damages, but this requires that you prove a loss occurred due to the infringement, which can be difficult. You may receive additional copyright protection by registering the work with the copyright office. For example, you can get “statutory damages”, compensation fixed by law that does not require proving an actual loss.

Who Owns Your Code?

Therefore you own the copyright to every line of code you write. Well… sort of.

The code a developer writes while an employee or client fall under the doctrine of “work for hire” and therefore belong to the employer (or client). Some independent contractors will stipulate in their service agreement with the client that even though the client owns the copyright to the code, the client shall give the contractor a non-exclusive license to the code.

Next Time: Licensing

In the next post in this series, I will discuss licensing and get into the nitty gritty as it pertains to open source software. Many thanks to my friend Walter Impert for his legal editing.

open source comments suggest edit

This is part 2 in my three-part series on copyright law and software licensing. Part 1 covered the basics of copyright law. With the background knowledge from that post, we are ready to tackle software licensing in more depth. After this, continue onto Part 3 of the series.

Licensing In General

A license is permission granted by a copyright holder to others to reproduce or distribute a work. It is a means to allow others to have some rights when it comes to using a work without assigning the copyright to others.

For example, although I own exclusive copyright to this very blog post, at the bottom of every page in my blog I provide a license to freely copy, distribute, display, and perform the work. I also allow making derivative works and commercial use of the work under a Creative Commons license. Gee what a nice guy I am! However I do stipulate one restriction. Anyone who wishes to exercise one of the listed rights within the license must attribute the work to me and make clear to others the license terms for the work. As the copyright holder, I am free to grant others these rights, but also to add restrictions as well.

Proprietary and Closed Source Licenses

Copyright law and licensing applies to software every bit as much as it does to writing. Most of the software that the average person uses day to day falls under a proprietary license. That is, the user is not free to distribute the software to others. This is often called “closed source” software, but that term may be slightly misleading as software can have its source code visible, but still not allow open distribution. Likewise, it is possible for closed-source software to allow others to freely distribute it as in the case of many free utilities.

Open Source and Free Software Licenses

This leads us finally to “Open Source Software” and “Free Software”. The two terms are often used interchangeably, but there is a slight distinction. The term “Free Software” tends to apply to software licensed in such a way that any code that makes use of the free software code must itself be freely available. The “free” in “Free Software” applies to the freedom to view the code.

Whereas “Open Source” is a more blanket term that merely applies to software in which the source code is visible and freely distributed. Open Source software does not necessarily require that its usage also be Open Source. Thus Free Software is Open Source, but Open Source is not necessarily Free Software.

Types of Open Source Licenses

When starting an open source project, the copyright owner is free to license the source code to others in any manner he or she sees fit. But the cost to draft a custom open source license is prohibitive. And to do so oneself is often a big mistake, especially given the fact that there are many well established licenses in existence that have stood the test of time.

Choosing A License

The Fogel book does a decent job of providing insight into how to choose a license, so I won’t delve into it too deeply.


Despite the plethora of licenses, in general the one you choose will be a result of your philosophical disposition towards open source software. If you fall under the free software camp and believe that all software should be free, then you may gravitate towards The GNU General Public License (GPL).

The GPL is designed to guarantee the user’s freedom to share and change the software licensed under its terms. When using GPL code, no additional restrictions may be applied to resulting product. In this way, the GPL is similar to the Borg. If you wish to use GPL code within your own project, then your own project must be licensed in a compatible manner with GPL. Thus GPL code tends to begat more GPL code. It is not permissible under the GPL to use GPL in proprietary software while keeping that software closed source.

MIT and BSD Licenses

For others with no philosophical objection to using open source software within proprietary software, the MIT license or the new BSD license may be more appropriate.

In essence, these licenses do not provide any restrictions on how the software may be copied, modified, or incorporated into other projects apart from attribution. Thus you can take code from a BSD licensed project and incorporate it into your proprietary software. You can even try to sell BSD licensed software as is (technically you can do this with GPL too), but this is as difficult as selling ice to Eskimos. Because you cannot restrict others from simply obtaining the source code, selling open source licensed software as is makes for a difficult proposition. You had better add a lot of value to be successful. Popular .NET projects such as Subtext, DasBlog, and RSS Bandit are all licensed under the BSD license.

UPDATE 2013/07/17: GitHub recently created a site to help folks unfamiliar with licensing make an informed choice. It’s called and worth checking out.

Stay Tuned for Part 3.

comments suggest edit

Well today completes my 31^st^ trip around the Sun and what a Birthday weekend it has been! Every now and then I like to buy a Super Lotto ticket just for the fun of it. I have a solid understanding of math (I did major in it) and I know that the odds are pretty much zilch, but it is fun to think about what I would do should I win.

Well I can stop thinking and start doing because I did win! I matched three number and the MEGA for the Jan 18 drawing winning me a grand total of $47.00! Woohoo! Forty-seven smackeroos! I definitely will NOT spend it all in one place (unless I fill up on gas). Since it is a jackpot under $600, I can simply walk over to the store where I bought it and claim my prize.

Apart from the Super Lotto, this weekend reminds me that I have won many other lotteries in life. Saturday we had some friends over for a birthday party at our place and it is quite clear that I have won the lottery of friends. My wife organized the whole thing and cooked up an amazing curry. I have definitely won the lottery of wives. And yesterday, in the opening game for my soccer league, I had an assist and I scored a pretty sweet goal in the first 60 seconds of the second half, winning the lottery of…er…that game four to nill. Ok the lottery analogy has fallen apart.

To you that find this post, I hope you win the important lotteries in your life as well.

comments suggest edit

The key purpose of my last post was to demonstrate how the ASP.NET web controls follow the Decorator pattern when it comes to rendering and how developers can hook into that to customize the rendered HTML.

The example I demonstrated made a Button control render XHTML conformant markup. My article applies to ASP.NET 1.1. However, one commenter pointed out an even easier approach if you are working with ASP.NET 2.0. You can simply set the xhtmlConformance elment in Web.config. For example:

<xhtmlConformance mode="Transitional"/>

Well, I am sure you’ll find other uses for the decorator technique I wrote about.

open source comments suggest edit

Every open source project has its own procedures for granting the all-important commit access to developers. Some require a set number of submitted patches (which Fogel, author of Producing Open Source Software, warns against). Others do not have any clear process and rely on the whims of those with the ability to add other committers. Whichever procedure your project chooses, it is important make sure make sure it is clearly published in a visible location such as in the developer guidelines.

Fogel discusses the methods by which the Subversion project grants commit access, emphasis mine.

In the Subversion project, we choose committers primarily on the Hippocratic Principle: first, do no harm. Our main criterion is not technical skill or even knowledge of the code, but merely that the committer show good judgement. Judgment can mean simply knowing what not to take on. A person might post only small patches, fixing fairly simple problems in the code; but if the patches apply cleanly, do not contain bugs, and are mostly in accord with the project’s log message and coding conventions, and there are enough patches to show a clear pattern, then an existing committer will usually propose that person for commit access. If at least three people say yes, and no one objects, then the offer is made. True, we might have no evidence that the person is able to solve complex problems in all areas of thecode baes, but that does not matter: the person has made it clear that he is capable of at lest judging his own abilities. Technical skills can be learned (and taught), but judgement, for the most part, cannot. Therefore, it is the the one thing you want to amke sure a person has before you give him commit access.

Obviously, one problem with this approach for very small projects is you might not even have three committers. This merely reinforces the fact that any policy should fit the size of the project and should be amended as the project grows. But its emphasis on judgement as opposed to technical skill is, in my opinion, a good one.

On any project, there will always be plenty of small tasks that do not require Linus Torvalds to get it done. Rather they can be handled by Joe Hobbyist and Jill N00b, as long as they exercise good judgement. And having someone focused on these smaller easy tasks helps the overall polish of the application, as the “serious” developers often do not spend their time on them.

Another benefit of this approach is that it does not rely on an artificial quota, but on recognition by other committers that someone exhibits good judgement. Ostensibly, if the other committers were chosen because of their good judgement, they can most likely be trusted to use good judgment when recommending and voting on other committers.

I recommend reading the book to delve into the actual procedures for handling the voting and making the offer.

comments suggest edit

Man! What a mouthful of a title, but I think it succinctly describes what this post is about. I will demonstrate how to hook into the rendering of a control that inherits from System.Web.UI.WebControls.WebControl using a Decorator. In particular, I am going to hook into the rendering of a Button control to stop it from emitting the language="javascript" attribute.


Because I am a bit anal about XHTML compliance. The Button control renders an input tag with the language attribute. But according to the XHTML 1.0 transitional spec, this is an invalid attribute.

More than just being anal, I also thought it would serve as a nice demonstration of this technique in case you want to build custom controls that modify the rendering of other controls just slightly without having to rewrite a lot of code.

First Naive Attempt

My first attempt to handle this was to simply try and remove the language attribute via the following code placed in the OnPreRender method of my page:


That didn’t work because the button control doesn’t explicitly add the language attribute to the attributes collection. Instead, the attribute is added within the Render method which is called by the page when it is time for a control to render its contents to HTML.

Examining The Rendering Process

The Render method is passed an instance of HtmlTextWriter used to render the page. One of the methods on this class is AddAttribute which has several overrides. Using Reflector I found that the method that adds the language attribute has the signature AddAttribute(string name, string value);.

The Decorator

Now if only I had some way to override that method to discard attributes with the name “language”. That’s where the decorator pattern comes in.

The class I want to decorate is the HtmlTextWriter. Fortunately the authors of this class did a good job of making it extensible and easy to decorate. HtmlTextWriter has a constructor that takes in an instance of TextWriter. Methods on the HtmlTextWriter use the specified TextWriter to write to the underlying stream. The good news is that HtmlTextWriter inherits from TextWriter. So if I want to hook into the rendering process, I just need to implement my own HtmlTextWriter and override the specific methods I need.

The CompliantButton class

The first step is to create a CompliantButton class that inherits from Button. Within that class I created a private internal class named CompliantHtmlTextWriter like so:

private class CompliantHtmlTextWriter : HtmlTextWriter

    internal CompliantHtmlTextWriter(HtmlTextWriter writer) : base(writer)
    /// <summary>
    /// Ignores the language attribute for the purposes of a submit button.
    /// </summary>
    public override void AddAttribute(string name, string value, bool fEndode)
        if(String.Compare(name, "language", true, CultureInfo.InvariantCulture) == 0)
        base.AddAttribute (name, value, fEndode);

This is the decorator. Notice that the constructor takes in another HtmlTextWriter which it will forward method calls to. The AddAttribute method simply forwards calls to the base class unless the attribute name is “language”.


Now all that is left is to use the decorator within the render method of the CompliantButton class. Here is the render method:

protected override void Render(System.Web.UI.HtmlTextWriter writer)
    base.Render(new CompliantHtmlTextWriter(writer));

Notice that I am wrapping (decorating) the HtmlTextWriter parameter with my CompliantHtmlTextWriter decorator before passing it along to the base Render method. As far as the base Render method is concerned, it is dealing with an HtmlTextWriter. It doesn’t need to know any specifics about the decorator class. But via decoration, the behavior has been slightly modified. No more language attribute.

comments suggest edit

Cash Money If you are going to talk about a product named “Microsoft Money” you had better make sure your comment spam filter doesn’t barf on the word “money”. That just wouldn’t be nice to the helpful people with legitimate comments.

My apologies to those who were frustrated by my blog puking on your well intentioned comments. I had previously assumed nobody had a good reason to comment me abount money. But then I started talking about it. Eeeediot!

comments suggest edit

One key component of open source projects is getting others involved in code review. In fact, that has always been one of the promises of open source software that with the hundreds and thousands of eyeballs looking at the code, the quality will be higher. In practice this doesn’t necessarily work out because the majority of open source projects only have a few eyeballs at work.

Also, in order to get those eyeballs reviewing code, the bar of entry must be low. Requiring users to set up CVS and track commit logs is a major hurdle. That’s where commit emails come in. Commit emails are triggered by a commit to the source code repository and typically contain the log message of the commit, which file or files were changed, and a diff of the changes.

Having others review commit emails also keeps people honest in their log messages and provides a means to help propagate and support project standards.

Originally I intended to generate an RSS Feed for commits, but I found that the approach I was taking was impossible in SourceForge. SourceForge does not allow writing to the Web Shell Services from scripts running within CVS. However, I have another idea brewing that won’t require file write access to the shell web services, but I#&8217;ll need to brush up on Python first.

Sourceforge uses CVS syncmail for sending out email notifications of commits within CVS. Each email provides the log message and a diff (an example is at the bottom).

Setting this up is pretty well described by the documentation. The only thing I have to add is that to checkout the CVSROOT module, follow the same instructions for checking out the project’s main module as I wrote in the past , but enter “CVSROOT” for the Module name at the bottom of the TortoiseCVS dialog.

This is currently set up for Subtext (click here if you wish to subscribe).

Example of a commit message

Update of /cvsroot/subtext/CVSROOT
In directory

Modified Files:
Log Message:
Changing the comment for the purpose of testing commit emails.

Index: loginfo
RCS file: /cvsroot/subtext/CVSROOT/loginfo,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** loginfo 16 Jan 2006 17:02:50 -0000  1.7
--- loginfo 16 Jan 2006 17:07:31 -0000  1.8
*** 27,33 ****
  #DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog
! # This line sends all changes to the CVSROOT module to the user specified ! # by USERNAME. It is recommended that someone be watching this module ! # as it shouldn't need to be modified very often.
  CVSROOT /cvsroot/sitedocs/CVSROOT/cvstools/syncmail %{sVv}
--- 27,32 ----
  #DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog
! # This line sends all changes to the CVSROOT module to the specified email address.  
! # This module shouldn't need to be modified very often.
  CVSROOT /cvsroot/sitedocs/CVSROOT/cvstools/syncmail %{sVv}

comments suggest edit

I really appreciate how Microsoft has really opened up many of its internal developer groups. I only wish this also applied to more of their consumer products.

For example, I am trying to set up online services for a bank within Microsoft Money. My bank allows passwords up to 32 characters. Microsoft Money allows me to enter 8 characters and that’s it. WTF!? With all this emphasis on security, you’d think they would support more than 8 characters in a password, especially when the bank does.

So I try going to the support site and there is nothing helpful. Since my copy is over a year old, I get the lovely option to pay $35.00 for a support incident. Heck for that money, I might as well upgrade, but how do I know this problem is even fixed in the latest versions? I don’t.

So following the support instructions, I head over to the Microsoft Money community newsgroups to be greeted with the message…

Service Temporarily Unavailable

We apologize for this inconvenience. Please try again later.

Great! It appears there is no way for me to register a complaint or have someone tell me whether this is fixed in the latest version of Money for this institution. Maybe I should have bought Quicken.

code, open source comments suggest edit

Producing Open Source Software
Cover I just finished reading the book “Producing Open Source Software - How to Run a Successful Free Software Project” by Karl Fogel (pdf available). CollabNet has employed Karl Fogel for the past five years to work on Subversion. Prior to that he has been involved with GNU Emacs and CVS development.

If you fall in one of the following categories, I highly recommend taking the time to read this book. Especially if you fall in one of the first two.

  • Planning to start an open source project
  • Currently running an open source project
  • Involved with an open source project
  • Managing a team of distributed developers

Much of this book is really a primer on how to work with and manage people. After all, open source development is really built on relationships more than even technical know-how. Manage the relationships well, and people will happily contribute. Do a poor job, and you may find interest lacking (though interest may lack for many other reasons as well).

But Fogel also delves into how to structure a project and administer the day-to-day activities that are required to run a project smoothly. Some of the topics he covers include:

  • How to choose a license
  • Who to give commit access to
  • Writing Developer Guidelines
  • Hosting and choosing version control
  • Managing communications
  • Assigning roles
  • Voting

And the list goes on.

It is my hope to start applying some of the principles he writes to open source projects I am involved with such as Subtext. Though Fogel’s experience and advice seems targetted to very large open source projects, I think much of it is useful for small projects as well. Besides, if you don’t prepare for growth, you will never see growth. And if you do grow big suddenly, it is better to be prepared than caught off-guard. But having said that, it is also important to adjust the level of formality in processes and structure to agree with the size of the project. So I won’t let myself get carried away.

Instead, I hope to start a short blog series to summarize and perhaps expand on certain principles gleaned from the book.

comments suggest edit

Tim Bray writes to correct misperceptions of what “Open Source” is about.

They both paint a picture of misguided innocents who believe in some starry-eyed vision of post-capitalist intellectual collectivism, but are actually pawns in the hands of larger economic forces. They’re both really wrong. Granted: Open Source is not a nation or a corporation or a political party or a religion. (While there are “movement people”, organized into the skeptical-of-each-other Open Source and Free Software sects, they are a tiny—albeit noisy—minority.) Absent those things, what is left? A collection of people who like working on software and actively seek out opportunities, preferably but not necessarily paid, to do so. If that is isn’t a “community”, what is?

Tim hits it on the mark. If Subtext is a pawn in some larger economic force, I’d be curious to find out which major corporate power seeks to gain, and perhaps ask them for some funding. ;)

In truth, there are many reasons people work on open source software, and they are not all the same. Many just find it fun to work on something more interesting than the boring data-in data-out systems they build at work. Some want to have a hand in building a better mousetrap. Many enjoy participating in a community and perhaps gaining a bit of recognition among their peers. A few see it as a political movement against capitalist interests. Yet others are paid to work on open source projects as it benefits their employer. None of these reasons are inherently wrong, misguided or amoral.

Many of these articles criticising open source focus on the big projects. What they fail to look at is that the majority of open source projects are very small. Many fill very niche markets that corporations have no interest in filling, but that there is yet a long-tail demand for.

comments suggest edit

Consider this a more advanced followup to my Quickstart Guide to Open Source Development With CVS and SourceForge.


So you have finally decided to become a flower power card carrying community loving member of an an open source project that happens to be hosted on Sourceforge. Good for you! Unfortunately, someone might expect you to actually contribute something. Suppose they give you the responsibility to update the project Home Page. SourceForge provides the ability to host project home pages within SourceForge itself, but how do you access those files? This guide will help you with that so you can earn the respect of your peers and graduate from n00b to contributor.

First, it is important to understand that you will not be able to fallback on your trusty FTP client to move your files to your SourceForge website. If you are a Windows developer unnaccustomed to the *nix-y ways of doing things (*nix == unix, linux, anyothernix…), it’s time to get the hands a bit dirty. But don’t you worry, I’ll present the most Windowsy manner to get *nixy tasks done.

To access files on SourceForge, you are going to have connect to their shell services via an SSH session. SSH is a protocol which is analogous to, but different from FTP. Some applications adopt this protocol to provide secure communication between servers, such as SFTP (secure FTP) and SCP (secure copy). Applications which are not built on SSH can still use these services by communicating through an SSH tunnel.

WinSCP To Securely Transfer Files

The quick and easy way to do this for those of us who don’t work with *nix every day is to download and install WinSCP. WinSCP is both a SFTP (SSH File Transfer Protocol) and SCP (Secure Copy Protocol) client.

SourceForge Project Shell Info

Before you start with WinSCP, you’ll need some information about your SourceForge project handy. Remember, as with all things *nix, everything is case sensitive.

  • Hostname: (or
  • Username: as used to login to the web site.
  • Password: Password authentication is not supported. You must configure a SSH key pair for authentication.
  • Project Group Directory: /home/groups/P/PR/PROJECTNAME
  • Project Web Directory (root): /home/groups/P/PR/PROJECTNAME/htdocs
  • Project Web CGI Script Directory: /home/groups/P/PR/PROJECTNAME/cgi-bin

For example, these values for me on Subtext are…

  • Hostname: (or
  • Username: haacked
  • Password: leave blank
  • Project Group Directory: /home/groups/s/su/subtext
  • Project Web Directory (root): /home/groups/s/su/subtext/htdocs
  • Project Web CGI Script Directory: /home/groups/s/su/subtext/cgi-bin

Using WinSCP

When WinSCP first starts, you will see a dialog box that requests various host information. Enter the following details in to the provided dialog box:

  • Host name: (or
  • Port number: 22
  • User name: YOUR_USERNAME
  • Password: leave this field blank
  • Private key file: Click on the “…” button to browse for the PuTTY private key you created previously following the instructions here. Load the desired key.
  • Protocol: SFTP (allow SCP fallback)

Below is a screenshot of this dialog and how I entered the fields.

Click Save and choose the default for the session name which should matche the hostname you entered previously ( or

To start the session, click the Login button. The first time you do this for a session, you will get a dialog asking to compare the SSH host key fingerprint. This is to make sure you are connecting to the site you think you are connecting to.

If you followed the instructions as I described, you should see the following key:


If yours differs, compare it against the list of keys here. If it does not match, please contact staff by submitting a Support Request.

Once you are logged in, you can browse your project directories. Browse to your project root and if you choose the Explorer view as I did, it should look like the screenshot below.

WinSCP ScreenShot

Place your web files within the hcp directory. Unfortunately at the time of this writing, SourceForge won’t run .NET code, but it does support cgi as well as PHP and MySQL.


comments suggest edit

Vista From reading other blogs, it seems many developers are unimpressed with the sheen of Windows Vista, the next version of the Microsoft operating system. There is definitely appreciation for all the improvements under the hood, but the out-of-box experience (at least in the betas), leaves much to be desired.

That is why I love this post from Jon Galloway that first points to some videos that compare Vista to Mac OSX (released 2002). He then lists several ways that Microsoft could inexpensively do better. My favorite quote is this…

…you’ve got Paint.NET, which stomps MS Paint so badly I have to turn my head away and sob.

comments suggest edit

A while ago I wrote up a Quick and Dirty Guide to Configuring Log4Net for Web Applications. Today I received an email asking how to set up logging for a web application that also consists of a business layer and a data access layer.

The Situation

This person had the following three projects setup as part of his VS.NET Solution:

  • ASP.NET Web Application Project
  • Business Layer Class Library Project
  • Data Access Layer Class Library Project

Note that the Web Application project has a project reference (or assembly reference) to the Business Layer, which in turn probably has a project reference to the Data Access layer. These assemblies will be deployed with the web application and will not be hosted on separate servers, thus remoting does not come into play here.

The developer added a Log4Net.config file to each project as well as the AssemblyInfo directive described in my post. The goal was to get all three projects logging to the same file. For the two class library assemblies, the developer specified the full system path to the log file.

The Explanation

To understand why this doesn’t necessarily work, we have to step back and look at how configuration settings are picked up by a .NET application in general. Suppose we were’t dealing with Log4Net for a second, but wanted to configure some app settings? Would it require that we add an App.config file to the Business Layer and Data Access layer project? Indeed no. These are class libraries. They do not contain an execution entry point as an executable does. We simply need to add a web.config file to the Web Application Project and we’re set.

The main reason for this is that configuration settings apply to the executable application (in this case a web app). You can certainly include code within the business layer assembly to read app settings, but it reads the settings from the web.config or App.config file in the execution startup path.

Note: I am doing a bit of hand waving here. Technically, the ASP.NET web application assembly is not an executable, it is a class library. However due to how the ASP.NET runtime works, it exhibits some of the behavior of being an executable and for the purposes of this discussion we’ll leave it at that. One key difference though is that for executables, the config file must be named the same as the assembly with a config extension and put in the same directory as the executable (typically bin), whereas with an ASP.NET application, the config file is always named “web.config” and placed in the web root, not in the bin directory.

This is also how Log4Net configuration works. Remember that when you build the web application, your business layer and data access layer assemblies will be copied to the bin directory of the web application. Thus all three assemblies are in the same location, so there is no need to specify a different Log4Net.config file for each assembly.

When you think of it, this makes sense. Your business layer assembly is a class library, thus it can be used and re-used in more than one project. It is not an execution starting point, but is called into by another executable. You wouldn’t want that assembly to specifiy where it logs its messages. You would rather have the consumer of the assembly do that.

The Answer

So the answer to the question is to make sure that both the business layer and data access layer projects do NOT include a Log4Net.config file nor the AssemblyInfo directive. They do not need it. It will be up to the consumer of these assemblies (the execution starting point) to configure logging.

All you need to do in these assemblies is to add an assembly reference to the Log4Net assembly and make calls to its logging methods in your code just as you would in the web application layer.

Then configure your web application as mentioned in my dirty guide and you are all set. Log messages from all three assemblies should funnel nicely to your log file.

To demonstrate this, I set up another sample VS.NET 2003 solution. It is based on the same project that I included in my previous article on the subject, but includes a business layer class library. The web application references the class library and makes a method call that logs a message. The class library references Log4Net, but does not include the Assembly directive nor the Log4Net.config file.

Download it, set up the IIS directory, and visit the default page. You’ll see log messages from within the business layer as well as the web application in the log file.

code, css comments suggest edit

On a recent project, my team pursued a CSS based design as we had two sites to build that were similar in layout, but different in look and feel. We were brought in after the schematics and design had pretty much been worked out, but we felt we could work with the agreed upon design.

The site had a typical corporate layout: a header, a body, and a footer. The body might have two or three columns. We started off writing markup that had a structure like so (not including the body columns).

<div id="main">
    <div id="header"></div>
    <div id="body">Body</div>
    <div id="footer">Footer</div>

We set the logo using CSS by applying a background image to the header div.

    background: url(logoExample.jpg);
    width: 180px;
    height: 135px;

Which produces something that might look like this (Trust me, the real thing looks a lot better)…

So everything is fine and dandy till we place the site on a staging server and the client asks that the header logo link back to the main page. This wasn’t in any of the requirements or design spec, but it is perhaps something we could have guessed as it is quite common.

So how do we make the logo image be a clickable link to the main page? My first inclination was to abandon using a background image and make the logo a regular image. The markup would look like (changes in bold)…

<div id="main">
    <div id="header">
        <a href="/"><img src="images/logoExample.jpg"></a>
    <div id="body">Body</div>
    <div id="footer">Footer</div>

But I found a better way to do this based on a technique I saw in “Bulletproof Web Design”. I changed the markup to be like so…

<div id="main">
    <div id="header">
        <a href="/" title="Home"><h1>Title</h1></a>
    <div id="body">Body</div>
    <div id="footer">Footer</div>

I then changed the css for the anchor tag to have the same dimensions as the logo image. I positioned it so that it would fit exactly over the image.

    background: url(logoExample.jpg);
    width: 180px;
    height: 135px;
    position: relative;

#header a
    position: absolute;
    top: 0;
    left: 0;
    width: 180px;
    height: 135px;

#header a h1
    display: none;

Notice that I had to add position: relative; to the header element . That ensures that the absolute positioning applied to the header link is relative to the header and not the entire document.

Now the header logo image appears to be a clickable link. Problem solved. I am pretty sure that others have pioneered this trick, but I hadn’t seen anything written up. What I read applied to making clickable tabs.

UPDATE: As Klevo mentioned in the comments, I really shouldn’t have an anchor tag without any text. Including text would be good for search engine optimization and for those who view the site without CSS. Shame on me, especially after reading the bulletproof book.

But to my defense, it was peripheral to the main point I was making. However that doesn’t excuse it as bad samples have a way of proliferating. So I corrected the sample above. The anchor tag now includes the title of the blog, but sets the title to be invisible.

comments suggest edit

Can’t use your favorite IM tool because of a pesky firewall at your place of work? Kyle points me to this web app, Meebo which appears to be in the alpha phase, but worked fine for me. It allows you to sign in to one of several popular IM services and use a rich web-based client.

So if your worksite allows you to browse the web, you can also chat.

Here’s a screenshot of a section of the login page.

Login Screen

According to the site, passwords are encrypted with 1024-bit RSA keys. Below is a screenshot of a Yahoo Messenger session. Notice the nice transparent effects when highlighting a profile.

Meebo in action

comments suggest edit

I can get a bit overboard with my virtual paths. I tend to prefer virtual paths over relative paths since they feel safer to use. For example, when applying a background image via CSS, I will tend to do this:




    background: url(‘/images/bg.gif’);


My thinking was that since much of the code I write employs URL rewriting and Masterpages, I never know what the url of the page will be that references this css. However my thinking was wrong.

One problem I ran into is that on my development box, I tended to run this code in a virtual directory. For example, I have Subtext running in the virtual directory /Subtext.Web. So I end up changing the CSS like so:




    background: url(‘/Subtext.Web/images/bg.gif’);


Thus when I deploy to my web server, which is hosted on a root website, I have to remove the /Subtext.Web part. Now if I had read the CSS spec more closely, I would have noticed the following line:

Partial URLs are interpreted relative to the source of the style sheet, not relative to the document.

Thus, the correct CSS in my case (assuming my css file is in the root of the virtual application) is…




    background: url(‘images/bg.gif’);


Now I have true portability between my dev box and my production box.

It turns out that Netscape Navigator 4.x incorrectly interprets partial URLs relative to the html document that references the css file and not the css file itself. Perhaps this was where I got the wrongheaded notion embedded in my head way back in the day.

personal comments suggest edit

Pimped Desktop Ryan Farley gives the lowdown on his tricked out desktop.

In the past I’ve tried to get into tricking out the desktop, but everytime I switched to a new computer, I felt less and less inclined to do invest the time. Besides, I remember some of these programs would slow down the OS. I like my desktop to be lean and mean.

But after seeing Ryan’s screenshot, I may have to consider playing around with some of the customizations.

It’s funny to me how many geeks I know would dread spending time selecting drapery and customizing the small details of their house (“Pick any color, honey. I don’t care.”) yet will obsess over every pixel of their desktop.