Home ::  Admin

chris carter's web log

Exceptions Gone Wild

7:14 AM Thursday Mar 27, 2008 Comments: 0

This post on when to throw exceptions got me thinking about how I throw exceptions.  I usually follow the rules suggested in the post, Fail Fast and Exceptions Should Be Exceptional

Along with the fail fast approach, I will throw exceptions from a constructor if the class cannot function appropriately with invalid args, or with args that would put the use of the class at risk.  The author had a slightly different point of view on that: 

If the ctor needs to throw an exception when in invalid state, it need to know about all invalid state and all usages of the class.

 I don't believe this is necessarily the case.  If I have this class:

public class InventoryManager{
  private WarehouseServiceProxy _proxy = null;

  public virtual bool InStock(int productID){
    int count = _proxy.GetRemaining(productID);
    return count > 0;
  }

  public virtual string GetProductDescription(int productID){
    Product product = _proxy.GetProduct(productID);
    return product == null ? "Product Not Found" : product.Description;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

I tend to prefer to find out immediately when something is going to break. In this case, as soon as I create an instance of InventoryManager(as I may only create this once).  I don't need to know about all usages of the class, but I do know that the core functionality of the class resides around the WarehouseServiceProxy being not null.  This class depends on the fact that there is a valid instance of WarehouseServiceProxy, so I'd add this constructor:

public InventoryManager(WarehouseServiceProxy proxy){
  if(proxy == null)
    throw new ArgumentNullException("proxy", "proxy cannot be null");
  _proxy = proxy;
}

1
2
3
4
5

And the class would now look like this:

public class InventoryManager{
  private WarehouseServiceProxy _proxy = null;

  public InventoryManager(WarehouseServiceProxy proxy){
    if(proxy == null)
      throw new ArgumentNullException("proxy", "proxy cannot be null");
    _proxy = proxy;
  }

  public virtual bool InStock(int productID){
    int count = _proxy.GetRemaining(productID);
    return count > 0;
  }

  public virtual string GetProductDescription(int productID){
    Product product = _proxy.GetProduct(productID);
    return product == null ? "Product Not Found" : product.Description;
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Same logic applies to methods.  OK, so let's say that we've successfully created an instance of our InventoryManager, and we want to call the Save(Product) method which looks like this:

public virtual Product Save(Product product){
  return _proxy.SaveProduct(product);
}

1
2
3

The problem with that code is that what happens if product is null?  It's still going to waste a call to the service proxy only to return a null reference exception.  I would write the method this way:

public virtual Product Save(Product product){
  if(product == null)
    throw new ArgumentNullException("product", "product cannot be null");
  return _proxy.SaveProduct(product);
}

1
2
3
4
5

Really it comes down to pushing the checks for validity closer and closer to the client.  Even in the last example, why would you even call the save product method if product was null to begin with? Then you need to figure out, well why was product null? Keep fixing those things and you end up with a pretty solid system not riddled with exceptions.

On A Side Note

(Keep in mind I have the sense of humor of an 12 year old) I went to use the google search box in firefox to search on fail fast and as soon as I got to fail fa i got this suggestion:

Actually searching on fail fatty gave me this first hit, bad motivational posters.  I'm not sure which poster is my favorite, the Fatherhood one is pretty funny though.

DNAP: Dumb Name, Great Concept

10:23 PM Tuesday Mar 25, 2008 Comments: 0

So I'm cleaning up some past entries that I recently moved over from my dasblog days.  I found this one on dynamically building html with StringBuilder.  Interestingly enough it contained what I think is a neat concept.  Built in help for ajax methods.  Check this out. 

Anyone who's used AjaxPro or even Microsoft Ajax, knows making ajax calls requires knowledge of how to call the methods on the server side. Sometimes we forget, and it would be nice to have a reminder.  Sometimes we also need to know the javascript being generated that we're supposed to call.  WHAMMO! Check this out.

That's cool,  but there's not much there, what's this about a BaseRequest?  Well, presto, chango WHAMMO! Check this out.  It all comes down to the Ajax.Request

Neato.  Not really.  What's the point? This is all generated on the fly by this class definition:

public partial class AjaxTesterDemo : DNAP.AjaxPageBase
{
  [DNAP.GenericAjaxMethod]
  public string Echo(string name, int age, DateTime birthDate)
  {
    return String.Format("name: {0}, age: {1}, birthDate: {2}",
      name, age, birthDate.ToString("MM/dd/yyyy"));
  }
  [DNAP.GenericAjaxMethod]
  public string GetName(string socialSecurityNumber)
  {
    return String.Format("Ozzy Osbourne[ssn:{0}]", socialSecurityNumber);
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14

Any page that inherits from DNAP.AjaxPageBase inherits the ability to generate help pages for any ajaxish methods(basically any method adorned with an attribute that smells like ajax).

The current DNAP project is a .NET 1.1 app, I'm gonna clean it up and repost it prolly tomorrow.

HyperActive.Cream

5:31 PM Sunday Mar 23, 2008 Comments: 0

I tried doing a simple howto on HyperActive and ran into headache after headache.  I'm pretty sure, when you have problems using your own software, then something stinks really bad.  The main problem is the lack of guidance on using the console tool.  Is it missing something? Maybe, but the "dumb" stacktrace that says there's a nullreference exception somewhere doesn't help.  That's where HyperActive.Cream is coming from.  It's a complete re-design of the console UI of HyperActive, hactivate.

I have a lot to remember.  Most of all, I won't remember commandline switches, so first and foremost on the feature list for a console app is help, a feature of a command line tool that indicates, with examples, how to use the command line utility.  So that's the first priority of HyperActive.Cream, help.

Helpful ActiveRecord Hints

2:40 PM Sunday Mar 23, 2008 Comments: 0

I've added comment support to my ActiveRecord code generator, HyperActive.  The best part about this is adding comments that contain column properties about the database columns, take a look:

 

NHibernate Query Analyzer Example

8:11 AM Tuesday Mar 18, 2008 Comments: 0

OK.  Here is my Hello World type example for getting started with NHibernate Query Analyzer. Ayende's flash demo shows what the software does.

Create a Table

Here is the single table, contact, I'm using for this demo.

Create A Class That Represents The Table

Contact.cs

public class Contact
{
  private int _id;
  public virtual int Id
  {
    get { return _id; }
    set
    {
      _id = value;
    }
  }
  private string _firstName;
  public virtual string FirstName
  {
    get { return _firstName; }
    set
    {
      _firstName = value;
    }
  }
  private DateTime _birthDate;
  public virtual DateTime BirthDate
  {
    get { return _birthDate; }
    set
    {
      _birthDate = value;
    }
  }
  private string _email;
  public virtual string Email
  {
    get { return _email; }
    set
    {
      _email = value;
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

(note that the virtual keyword is required on the properties)

Create A Mapping File

Contact.hbm.xml is responsible for marrying our Contact class and properties with our contact table and it's fields.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
  xmlns="urn:nhibernate-mapping-2.2"
  namespace="Round1"
  assembly="Round1">
  <class name="Contact" table="contact">
    <id name="Id" column="contact_id">
      <generator class="native" />
    </id>
    <property name="FirstName" column="first_name" />
    <property name="BirthDate" column="birth_date" />
    <property name="Email" column="email" />
  </class>
</hibernate-mapping>

1
2
3
4
5
6
7
8
9
10
11
12
13
14

Create The NHibernate Configuration File

hibernate.cfg.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration
  xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="dialect">
    NHibernate.Dialect.MsSql2005Dialect
  </property>
    <property name="connection.connection_string">
    server=maximus;database=scratch;user id=nhquickie;password=nhquickie;
  </property>
    <property name="connection.driver_class">
    NHibernate.Driver.SqlClientDriver
  </property>
    <property name="connection.provider">
    NHibernate.Connection.DriverConnectionProvider
  </property>
  </session-factory>
</hibernate-configuration>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Write A Simple Test

Before heading over to NHibernate Query Analyzer I want to make sure what I've done at least works in visual studio. I created another project for the tests, here's test fixture that that does a simple save.

[Test]
public void CanSaveContact()
{
  ISessionFactory factory = new Configuration()
    .Configure()
    .AddAssembly(typeof(Contact).Assembly)
    .BuildSessionFactory();
  ISession session = factory.OpenSession();
  try
  {
    Contact contact = new Contact();
    contact.FirstName = "Riley";
    contact.Email = "riley@panteravb.com";
    contact.BirthDate = new DateTime(2004, 4, 11);
    session.Save(contact);
    Assert.IsTrue(contact.Id > 0, "Id should be greater than zero");
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex.ToString());
  }
  finally
  {
    if (session != null) session.Close();
    if (factory != null) factory.Close();
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

The Solution Structure

PreBuild Event

The hibernate.cfg.xml file needs to be in the current directory. I'm not entirely sure if this file should be in the same project as the tests or the mapping files. I stuck it in the project with the mapping files and added this prebuild event to the test project to copy the file over:

copy $(SolutionDir)Round1\hibernate.cfg.xml $(TargetDir)

It works but it may not be a recommended solution.

Quick Screencast: Using NHibernate Query Analyzer

Download Code

Here's the solution. It's about a half meg so if you have a slow connection beware.  Oh, and it's VS2005 flavored. I'm using the assemblies that shipped with Castle RC3Here's the database script for the contact table, the name of my database is Scratch, you'll need to change this to work on your machine.

Discovering Your Own WTF

3:22 PM Sunday Mar 16, 2008 Comments: 2

I just found this one in my code, embarassing.  Can you spot the WTF?

guid.UniqueIdentifier = String.Format(
  String.Format("http://{0}/archive/{1}/{2}/{3}/{4}.aspx",
    context.Request.Url.Host,
    post.DateAdded.Year,
    post.DateAdded.Month,
    post.DateAdded.Day,
    post.EntryName
  )
);

1
2
3
4
5
6
7
8
9

Why Test Driven Development Kicks Ass

8:31 AM Sunday Mar 16, 2008 Comments: 0

OK.  So I'm playing around again with PrototypeDotNetNotReally.  I got to looking at this code sample:

new Element("select", "id=select1;")
  .Insert(new Element("option","value=1").Update("Chris"))
  .Insert(new Element("option","value=2").Update("Anja"))
  .Insert(new Element("option","value=3").Update("Riley"))
  .Insert(new Element("option","value=4").Update("Emmitt"))
  .Render(Console.Out);

1
2
3
4
5
6

It's alot of code, not too clean looking.  So I wanted to come up with a simpler and shorter way of doing the same thing. 

Write The Test First

So I started writing the code I wanted to write to achieve the desired outcome. Here's what I got:

[Test]
public void CanCreateSelect()
{
  string expected =
    "<select id=\"select1\" name=\"select1\">" +
    "<option value=\"1\">Chris</option>" +
    "<option value=\"2\">Anja</option>" +
    "<option value=\"3\">Riley</option>" +
    "<option value=\"4\">Emmitt</option>" +
    "</select>";
  string actual = new Select("select1")
    .AddOption(1, "Chris")
    .AddOption(2, "Anja")
    .AddOption(3, "Riley")
    .AddOption(4, "Emmitt")
    .ToString();
  Assert.AreEqual(expected, actual);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Run The Test and See If It Fails

I hit CTRL+SHIFT+T which is wired up to the TestDriven.NET client, and voila! Errors galore.

Write Some Code

Kind of a lot of errors, right? I haven't even written a Select class yet. So, I declare a class named Select.

Run The Test Again

I run the test and now it complains that there's no constructor on Select that accepts a string,and there's no declaration of the methods AddOption and Render.

Write Some More Code

OK, I declare the contructor, declare AddOption, but the Render method I don't want to reinvent, there's already one in the Element class I want to use. So I inherit from Element and I should be good to go.

Run The Test Again

Now it compiles but the test failed.  None of the options were rendered... The default implementation of Element's Render method handles rendering itself and it's own children as well as it's own attributes.

Select inherits from Element.  Element has no knowledge of any of Select's members.  So I need to be able to hook into the Render method and tell it to Render the Select's children(the Options).  

The Render method is already virtual, so I can override that and use the HtmlTextWriter that's passed in to do all the dirty work.   But I don't want to type in a ton of code that is already in Element...

Refactor

Here's the original Render method:

override public void Render(HtmlTextWriter html)
{
  if (this.Attributes.Count == 0)
    html.WriteFullBeginTag(this.TagName);
  else
  {
    html.WriteBeginTag(this.TagName);
    foreach (Attribute attr in this.Attributes)
    {
      html.WriteAttribute(attr.Name, attr.Value);
    }
    html.Write(HtmlTextWriter.TagRightChar);
  }
  foreach (Element child in Children)
  {
    child.Render(html);
  }
  if (!String.IsNullOrEmpty(this.InnerHtml))
    html.Write(this.InnerHtml);
  html.WriteEndTag(this.TagName);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

I need to intercept a few things.  I need to break out when the opening tag is being rendered, when the attributes are being rendered, when the content is being rendered and when the end tag is being rendered. So the Render method ends up having 4 method calls only, using Refactor! Pro makes this a snap with the Extract Method refactoring. Now I have this:

override public void Render(HtmlTextWriter html)
{
  RenderStartTag(html);
  RenderChildren(html);
  RenderContent(html);
  RenderEndTag(html);
}

1
2
3
4
5
6
7

The RenderStartTag actually was refactored to also call RenderAttributes. Here are those methods:

protected virtual void RenderAttributes(HtmlTextWriter html)
{
  foreach (Attribute attr in this.Attributes)
  {
    html.WriteAttribute(attr.Name, attr.Value);
  }
}
protected virtual void RenderStartTag(HtmlTextWriter html)
{
  html.WriteBeginTag(this.TagName);
  RenderAttributes(html);
  html.Write(HtmlTextWriter.TagRightChar);
}
protected virtual void RenderChildren(HtmlTextWriter html)
{
  foreach (Element child in Children)
  {
    child.Render(html);
  }
}
protected virtual void RenderEndTag(HtmlTextWriter html)
{
  html.WriteEndTag(this.TagName);
}
protected virtual void RenderContent(HtmlTextWriter html)
{
  if (!String.IsNullOrEmpty(this.InnerHtml))
    html.Write(this.InnerHtml);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

Nothin special however now my Select class can take advantage of those virtual methods. I only needed to override the RenderChildren method so I could get my options to render, here's the entire Select class in all it's glory:

public class Select : Element
{
  private List<Option> _options;
  public List<Option> Options
  {
    get
    {
      if (_options == null)
        _options = new List<Option>();
      return _options;
    }
  }
  private string _id = "";
  public string Id
  {
    get
    {
      return _id;
    }
  }
  public Select(string id)
    : base("select", "id="+id+";name="+id)
  {
    _id = id;
  }
  public virtual Select AddOption(object value, string text)
  {
    this.Options.Add(new Option(value, text));
    return this;
  }
  protected override void RenderChildren(HtmlTextWriter html)
  {
    foreach (Option option in this.Options)
    {
      option.Render(html);
    }
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

Here's the Option class, super simple, almost don't even need it, that may get refactored out, not sure at this point. I ended up overriding the RenderContent and RenderAttributes methods.

public class Option : Element
{
  private object _value;
  private string _text;
  public string Text
  {
    get
    {
      return _text;
    }
  }
  public Option(object value, string text)
    : base("option")
  {
    _value = value;
    _text = text;
  }
  protected override void RenderAttributes(HtmlTextWriter html)
  {
    base.RenderAttributes(html);
    html.WriteAttribute("value", this._value.ToString());
  }
  protected override void RenderContent(HtmlTextWriter html)
  {
    html.Write(this.Text);
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Are We Done?

YES.  As soon as the test passes we're done.  I might continue writing tests that validated input, etc, but feature wise, we're done. We've written the least amount of code possible to achieve the desired behavior.

What Did We Gain?

The Select and Option classes are small and easy to read. They contain only the code necessary for the classes to do their job and nothing more.  No fluff. Just for kicks I reran the code coverage, now what's the percentage? We started with 100%, and now what do we have...(drum roll)...100%!  Adding only the necessary code to make the test pass guarantees that we maintain 100% code coverage.

Firefox 3 Dom Features

6:59 AM Sunday Mar 16, 2008 Comments: 0

The real improvements to new releases of Firefox(and any other browser)  come down to the developer slash web designer slash person typing in html/javascript with the hope that a browser will render it. 

I don't normally run through the feature lists of browsers but after installing Firefox 3, it sticks an informational page as the first page you see when you first start the browser following new installation.

Here is the actual page.  Click to the Web Developers link and you'll get to the page describing the Firefox 3 Dom Improvements.  It's kinda funny, they're supporting dom extensions that other browsers(IE mostly) have implemented, I like that. 

A nice new addition is the getElementsByClassName.  Normally I use prototype's $$ method for stuff like that but it's nice to see a new method that's hugely powerful.  Of course, this is probably going to be a place where IE is going to do it's own interpretation of the css matching rules so the method probably will not work the same in all browsers, who knows, for now I'm staying away from that method as well as any new dom extensions.

So, I'm pokin around the HTML 5 spec.  There's some cool stuff in there.  But really, what's the point? As of today anyway, I can't think of any possibility of ever supporting a new HTML spec that won't require web developers having to detect browsers and adding/removing behaviors of their content based on the browser viewing the page. 

I think HTML 4.01 is the last spec that will be taken seriously by the web community.  The only other options out there are going to be the technology jumps, where the browser is left behind in favor of products like ADOBE AIR and Microsoft Silverlight.

PrototypeDotNetNotReally

12:40 PM Saturday Mar 15, 2008 Comments: 0

I've been messing around now with elements and attributes and fluent interfaces.  Here is what i came up with:

It's super simple to create exactly those things and nothing else.  For example, to create a plain old html select element with some options you could do this:

new Element("select", "id=select1;")
  .Insert(new Element("option","value=1").Update("Chris"))
  .Insert(new Element("option","value=2").Update("Anja"))
  .Insert(new Element("option","value=3").Update("Riley"))
  .Insert(new Element("option","value=4").Update("Emmitt"))
  .Render(Console.Out);

1
2
3
4
5
6

And that code produces this html:

<select id="select1">
  <option value="1">Chris</option>
  <option value="2">Anja</option>
  <option value="3">Riley</option>
  <option value="4">Emmitt</option>
</select>

1
2
3
4
5
6

I'm trying to be WAY better about commenting code, not just for the sake of commenting but adding useful comments making it easy for intellisense to help while you're coding.  Adding simple examples to the method and/or property summary sections helps out by adding an extra layer of discoverability to your api.

Code coverage is a big deal for me.  I use NCoverExplorer that's built into TestDriven.NET.  Trying to hit 100% code coverage is hard to do, trying to get there can reveal a lot about how good your code is.  For this project, I noticed that some things not covered were things that actually didn't need to be in the code to begin with so I removed them.  Here's my code coverage report:

It's interesting to note that the Element and Attribute classes really are only useful if they're used as building blocks for frameworks of html controls.  Looking at the code for the html select example above reveals more code than I'd want to write if I had to use this.  It's pretty raw.  I might use the Element and Attribute classes directly if I had some VERY simple markup to return via AJAX.  I may never use them at all, it's fun playing though. 

Where did the name come from? Easy.  I suck at naming things and that was the first thing that popped into my head.  If you think it's a stupid name, you are absolutely correct.  If you think it's brilliant, you have had too much to drink and should go to sleep now.

Here's my solution with all of the code, VS2005 flavor.  It includes nunit.framework.dll, one project for the actual code, one for tests, and one website that has an amazingly stupid example in it.

Download Code Here

You like documentation? Here's my Sandcastle output.  I'm a huge Sandcastle noob and the code examples all look stupid, i need to figure that out.

Firefox 3 Beta 4: What's New

7:36 PM Thursday Mar 13, 2008 Comments: 0

I use Firefox as my primary development browser.  Past experience has taught me, if you do it right in Firefox, it will probably work in IE, if not there's probably already a hack for the issue on google. 

That said.  I have to wonder.  What can a new version of a browser offer that it's predecessor didn't? Speed? Better memory management? "More" standards compliant html rendering?

It seems like there is a fundamental problem with browsers.  I haven't been to web page recently that was parsed faster in firefox than ie or vice versa, or your favorite browser vs the other guy.  So for me, speed of parsing a page in todays world is nil.  I can only speak from end user experience.  If i bring up a page and it renders in less the one or two seconds, I am not capable of knowing, much less caring, if some other browser can render the content faster.

 So I installed Firefox 3 Beta 4 just now.  Went to google.com right off the bat and do you know what was different than version 2.x? Nothing.  Not one thing.  It brought up google.com just as fast as the last version that i just replaced.  Again, this is just from a plain ol' user, no scientific studies were conducted.

So what's new in Firefox 3 Beta 4?  I don't know.  I'd have to hit google to find that out.  My point is that I have simple needs.  Open browser, then view page.  Nothing more complicated than that.  Firefox 1.x did that great.  Firefox 2.x did it better although I wouldn't be able to quanytify that. 

There are probably some useful features that I'll find.

But at the end of the day, I open a browser and surf to pages.  That's it.  OK, maybe if I'm workin, I'll need the browser to be great at debugging, which Firefox trumps IE on debug-ability any day of the week. 

 So what major features does Firefox 3 bring to the table? Time will tell...

Code Smell

6:23 AM Wednesday Mar 12, 2008 Comments: 0

VS2008 will apparently let you know if your code stinks:

Keeping It Simple...Are You Sure?

12:49 PM Sunday Mar 9, 2008 Comments: 0

This post inspired me to write some fluent code.  Check it out:

[TestFixture]
public class ElementBuilderTests
{
  [Test]
  public void VerifyTagOnly()
  {
    Element table = new Element("table");
    Assert.AreEqual("<table></table>", table.ToString());
  }
  [Test]
  public void VerifyChildTags()
  {
    Element table = new Element("table", new Element("thead", new Element("th")));
    Assert.AreEqual("<table><thead><th></th></thead></table>", table.ToString());
  }
  [Test]
  public void VerifyAttributes()
  {
    Element table = new Element("table", "class=grid;height=100%;");
    Assert.AreEqual("<table class=\"grid\" height=\"100%\"></table>", table.ToString());
  }
  [Test]
  public void VerifyAttributesAndChildTags()
  {
    Element table = new Element("table", "class=grid",
      new Element("thead", new Element("th").Update("First Name"))
    );
    Assert.AreEqual("<table class=\"grid\"><thead><th>First Name</th></thead></table>", table.ToString());
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

I went and ported some of the basic functionality of the prototype Element class.  I don't like the way the author made it simpler, mostly cuz it made the syntax more complex.  I usually revert to using the HtmlTextWriter, or just a StringWriter, or sometimes a StringBuilder.

So I want to test out some different ways of generating html and we'll see which is the prettiest solution.  Here's what I need to generate:

<table class="grid">
  <thead>
    <tr>
      <th>First Name</th>
      <th>Last Name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Chris</td>
      <td>Carter</td>
    </tr>
  </tbody>
</table>

1
2
3
4
5
6
7
8
9
10
11
12
13
14

StringBuilder

This is pretty straight forward, for simple stuff I might go this route, but I tend to lean towards not entering the tag characters < and >.  This also can be hard to read code depending on the developer. 

StringBuilder html = new StringBuilder();
html.Append("<table class=\"grid\">");
html.Append("<thead><tr>");
html.Append("<th>First Name</th>");
html.Append("<th>Last Name</th>");
html.Append("</tr></thead>");
html.Append("<tbody><tr>");
html.Append("<td>Chris</td>");
html.Append("<td>Carter</td>");
html.Append("</tr></tbody>");
html.Append("</table>");
Console.WriteLine(html.ToString());

1
2
3
4
5
6
7
8
9
10
11
12

StringWriter

This is almost the same as the StringBuilder but can offer the benefit of WriteLine, so you can render the end of line character to the client for easier reading if you're debugging your html generation. In the StringBuilder example you could enter the end of line character but it's a sloppy solution and makes it harder to read. We're still writing the tag characters so I'm not in love with this solution.

using (StringWriter html = new StringWriter())
{
  html.Write("<table class=\"grid\">");
  html.Write("<thead><tr>");
  html.Write("<th>First Name</th>");
  html.Write("<th>Last Name</th>");
  html.Write("</tr></thead>");
  html.Write("<tbody><tr>");
  html.Write("<td>Chris</td>");
  html.Write("<td>Carter</td>");
  html.Write("</tr></tbody>");
  html.Write("</table>");
  Console.WriteLine(html.ToString());
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14

HtmlTextWriter

This should be the winner, right? NOPE. This is hugely verbose.  You don't have to type out the tag characters, yay, but you have to type in so much more it's almost not worth it.

using (StringWriter writer = new StringWriter())
using (HtmlTextWriter html = new HtmlTextWriter(writer))
{
  html.WriteBeginTag("table");
  html.WriteAttribute("class", "grid");
  html.Write(HtmlTextWriter.TagRightChar);
  html.WriteFullBeginTag("thead");
  html.WriteFullBeginTag("tr");
  html.WriteFullBeginTag("th");
  html.Write("First Name");
  html.WriteEndTag("th");
  html.WriteFullBeginTag("th");
  html.Write("Last Name");
  html.WriteEndTag("th");
  html.WriteEndTag("tr");
  html.WriteEndTag("thead");
  html.WriteFullBeginTag("tbody");
  html.WriteFullBeginTag("tr");
  html.WriteFullBeginTag("td");
  html.Write("Chris");
  html.WriteEndTag("td");
  html.WriteFullBeginTag("td");
  html.Write("Carter");
  html.WriteEndTag("td");
  html.WriteEndTag("tr");
  html.WriteEndTag("tbody");
  html.WriteEndTag("table");
  Console.WriteLine(writer.ToString());
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

HTMLHelper

This is using the code from the post that inspired my code adventures today. It's kinda weird because it's not really doing anything except maintaining a list of strings. It's up to the user to drive the html building using their favorite string concatenation technique, I used a StringBuilder.

StringBuilder html = new StringBuilder();
List<ElementAttribute> attributes = new List<ElementAttribute>();
attributes.Add(new ElementAttribute(HTMLHelper.CLASS, "grid"));
html.Append(HTMLHelper.BeginTable(attributes));
html.Append("<thead>");
html.Append(HTMLHelper.BeginRow());
html.AppendFormat("{0}{1}{2}",
  HTMLHelper.BeginCell(), "First Name", HTMLHelper.EndCell());
html.AppendFormat("{0}{1}{2}",
  HTMLHelper.BeginCell(), "Last Name", HTMLHelper.EndCell());
html.Append(HTMLHelper.EndRow());
html.Append("</thead>");
html.Append("<tbody>");
html.Append(HTMLHelper.BeginRow());
html.AppendFormat("{0}{1}{2}",
  HTMLHelper.BeginCell(), "Chris", HTMLHelper.EndCell());
html.AppendFormat("{0}{1}{2}",
  HTMLHelper.BeginCell(), "Carter", HTMLHelper.EndCell());
html.Append(HTMLHelper.EndRow());
html.Append("</tbody>");
html.Append(HTMLHelper.EndTable());
Console.WriteLine(html.ToString());

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

My Cool Ass Shit

OK. So I'm a little biased, but this sweet ass code is the clear winner(if there was even a contest to begin with). Anywho, I pretty much looked at the prototype api for Element and simulated some of that in csharp.

new Element("table", "class=grid",
  new Element("thead",
    new Element("th").Update("First Name"),
    new Element("th").Update("Last Name")),
  new Element("tbody",
    new Element("td").Update("Chris"),
    new Element("td").Update("Carter"))
).Render(Console.Out);

1
2
3
4
5
6
7
8

Here's the code, I was lazy and didn't package it up pretty as usual, it's just the csharp code file.

ActiveRecord Config Changes

5:17 AM Thursday Mar 6, 2008 Comments: 0

I'm filing this in the "huh, good to know" file.  This is if you're building from the trunk.  In the ActiveRecord config section the hibernate. prefix on the settings are no longer needed.  Found that out here.  So this:

<activerecord isWeb="true">
  <config>
    <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
    <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" />
    <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
    <add key="hibernate.connection.connection_string" value="ConnectionString=${pantera}" />
  </config>
</activerecord>

1
2
3
4
5
6
7
8

Becomes this:

<activerecord isWeb="true">
  <config>
    <add key="connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
    <add key="dialect" value="NHibernate.Dialect.MsSql2000Dialect" />
    <add key="connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
    <add key="connection.connection_string" value="ConnectionString=${pantera}" />
  </config>
</activerecord>

1
2
3
4
5
6
7
8

If you don't make that change you get this:

Sometimes Dog Fooding Sucks

10:13 PM Monday Mar 3, 2008 Comments: 0

And it should, that's the point.

This blog software, and I use the term "blog software" very lightly, had some pretty lame bugs floating around.

Comments were not saving most of the time.

RSS feed was not rendering text anymore.

I really let the first version of this thing go bad.  Here's why.  I kept testing stuff out in the same project I was delivering(granted, I was delivering it for me, but still).  So I had sample pages and code floating around that currently are just cluttering up the solution. 

I had to really work to figure out how my formatting stuff worked.  I'm pretty sure that's a sign that it sucks.  I wish I could remember where I got this from but it's a great saying slash quote slash whoever came up with it: Today, you and God know how your code works; tomorrow only God knows.

MUST

DOCUMENT

MORE

MUST

DOCUMENT

MORE