Another approach is to accept that the "ugly part" has to be implemented somewhere and provide an abstraction that hides the "ugly part" so that you don't have to repeat it in multiple places and can focus on the specific algorithm. This can be done using C# lambda expressions (or using C# 2.0 anonymous delegates if you're restricted to .NET 2.0):
void ForEachWithFirst<T>(IEnumerable<T> en,
Action<T> firstRun, Action<T> nextRun) {
bool first = true;
foreach(var e in en) {
if (first) { first = false; firstRun(e); } else nextRun(e);
}
}
Now you can use this reusable method to implement your algorithm like this:
ForEachWithFirst(websitePages,
(wp => sb.AppendLine(String.Format("<li class=\"first\">" +
"<a href=\"{0}\">{1}</a></li>", wp.GetFileName(), wp.Title)))
(wp => sb.AppendLine(String.Format("<li>" +
"<a href=\"{0}\">{1}</a></li>", wp.GetFileName(), wp.Title))) );
You could design the abstraction differently depending on the exact repeating pattern. The good thing is that - thanks to lambda expression - the structure of the abstraction is completely up to you.