It seems that one of the major problems for SEO experts is the forum post perma-link urls which come out as duplicated content urls. Which is to say that threads have links, and so do posts:
http://mycommunitysite.example.com/t/2323.aspx (the thread)
and any number of post urls like this:
http://mycommunitysite.example.com/p/2323/83839.aspx
Where the post ID as the page name is the individual post in the thread.
The simple solution is to use only thread references, right?. This isn't quite so simple if you have multiple pages to display posts. How do you indicate which page of the thread a post should link to? Posts can also be deleted or moved, which could affect page position for every post in a thread.
You can solve these problems in dynamic site links by changing post perma-links in a new ForumUrls provider:
public override string PostPermaLink(int threadID, int postID)
{
int _pageIndex = Posts.GetPageIndex(postID, PageSize, 0,
(int)CSContext.Current.User.PostSortOrder);
return ThreadPaged(threadID, _pageIndex) + "#" + postID.ToString();
}
This methodology has the mild inconvenience of requiring a set page-size for display of posts in a thread.
However, this doesn't solve the problem of what may be indexed. Once a link is stored, it may end up being on the incorrect page if posts are moved or deleted. Setting all of your post pages to noindex can help here. You could also set all of your thread display pages to list a very large number of posts at a time and virtually eliminate pages.
To really deal with posts and threads I think the best way would be to implement a script-based solution. Most crawlers don't implement script, which allows you to hide content from crawlers while still having a user-friendly implementation.
In a thread-centric implementation you could have only the thread page with all content on it, and implement paging via script. Post references are handled via anchors (as they can be in ootb CS).
My preference would be for a post-centric implementation where every post is in fact its own page and you implement the threaded view via client script. Links to 'threads' are in fact links to the thread-starter post.
When a post page is rendered you can dynamically 'locate' the post within the thread based on paging configuration.