Seems like the two big ones are Watin & Selenium. I haven't done any work with Selenium, so no opinion there.
I've used Watin a fair amount, and it's pretty good, but there are many issues. It can be hard to deal with wildly varying response times from a browser... setting timeout durations and the like.
The latest version of Watin supports IE & Firefox, which is pretty cool.
As far as test maintenance, in my experience the most important thing is to completely separate the "test driver" code from the "page-wrapping code". By "test driver" I mean the actual test logic (NUnit or similar) which might have code that looks like:
...
var wrapper = new SearchPageWrapper(browser);
wrapper.ClickAdvancedSearch();
wrapper.EnterSearchPhrase("dog");
wrapper.SetSortBy(SortType.Date);
wrapper.ExecuteSearch();
... the page-wrapper exposes this logical interface to the page itself while hiding the implementation details (which can be complex and change often with the page layout):
public class SearchPageWrapper {
...
public void ClickAdvancedSearch() {
_browser.Buttons("advSearch").Click();
}
public void EnterSearchPhrase(string phrase) {
_browser.TextBox(Find.ByName("phrase")).TypeText(phrase);
}
... etc ...
}
This way you build a library of wrappers that makes it easy to add new test cases, and also makes it less painful to deal with layout changes that affect the way that Watin finds & interacts with the elements on the pages.