I have finally managed to track down and fix the “unable to post a comment from feed readers” issue with Community Server. Unlike most of the other fixes, this one isn’t so trivial (and I knew as such going in…that’s why it’s taken so long). Moving onwards….
Out of the box, CS has virtually no implementation for CommentRSS (which is strange as .Text supports it 100%…curious as to why Telligent didn’t include it with CS). I followed the same pattern that .Text uses by implementing a custom httpHandler to intercept requests for a specific Url that comments are sent to from feed readers. The first thing you’ll need to do is add a new class in the CommunityServerBlogs project (in the Components/Syndication folder); name it RssCommentHandler.cs, and make sure to change the namespace to CommunityServer.Blogs.Components (as C# projects will include the full directory structure in the namespace by default…interestingly enough VB.Net doesn’t do this, defaults to the root namespace). Here’s the code you’ll need to add to the new class:
using System;
using System.Web;
using System.Web.Caching;
using System.IO;
using System.Xml;
// CS
using CommunityServer.Components;
using CommunityServer.Blogs.Components;
namespace CommunityServer.Blogs.Components
{
/// <summary>
/// Summary description for CommentHandler.
/// </summary>
///
// jayson.knight -- fix for posting comments from feed readers
public class RssCommentHandler : IHttpHandler
{
private RssCommentHandler() { }
#region IHttpHandler Members
public void ProcessRequest(HttpContext context)
{
HttpRequest request = context.Request;
if(request.RequestType == "POST" && request.ContentType == "text/xml")
{
XmlDocument doc = new XmlDocument();
doc.Load(request.InputStream);
User user = Users.GetUser();
int postID = getPostIDFromUrl(request.RawUrl);
WeblogPost commentedEntry = WeblogPosts.GetPost(postID, false, true, false);
Weblog blog = commentedEntry.Section as Weblog;
// if comments aren't enabled, throw an http forbidden exception
if (!blog.EnableComments)
{
throw new HttpException(403, "Comments are not enabled");
}
Permissions.AccessCheck(blog, Permission.View, user);
string name = doc.SelectSingleNode("//item/author").InnerText;
if(name.IndexOf("<") != -1)
{
name = name.Substring(0,name.IndexOf("<"));
}
WeblogPost post = new WeblogPost();
post.SubmittedUserName = name.Trim();
post.BlogPostType = BlogPostType.Comment;
post.SectionID = blog.SectionID;
post.ParentID = postID;
post.Body = doc.SelectSingleNode("//item/description").InnerText;
post.Subject = doc.SelectSingleNode("//item/title").InnerText;
post.TitleUrl = checkForUrl(doc.SelectSingleNode("//item/link").InnerText);
post.IsApproved = true;
post.PostDate = DateTime.Now;
post.BloggerTime = DateTime.Now;
WeblogPosts.Add(post, user);
}
else
{
}
}
private string checkForUrl(string text)
{
if(text == null || text.Trim().Length == 0 || text.Trim().ToLower().StartsWith("http://"))
{
return text;
}
return "http://" + text;
}
private int getPostIDFromUrl(string uri)
{
try
{
return Int32.Parse(getReqeustedFileName(uri));
}
catch (FormatException)
{
throw new ArgumentException("Invalid Post ID.");
}
}
private string getReqeustedFileName(string uri)
{
return Path.GetFileNameWithoutExtension(uri);
}
public bool IsReusable
{
get
{
return true;
}
}
#endregion
}
}
The next change is in CommunityServer.Blogs.Components.WeblogRssWriter.PostComments method. Add the following code:
// jayson.knight -- fix for posting comments from feed readers
// only write the wfw:comment tag if comments are enabled for this weblog
if (CurrentWeblog.EnableComments)
{
this.WriteElementString("wfw:comment", FormatUrl(BlogUrls.Instance().RssComments(CurrentWeblog.ApplicationKey,p.PostID)));
}
As we’re looking for a new RssComments Url, we need to modify the CommunityServer.Blogs.Components.BlogUrls class with a new method to find the rewritten Url; add this method to this class:
// jayson.knight -- fix for posting comments from feed readers
public virtual string RssComments(string applicationKey, int PostID)
{
return FormatUrl("weblogRssComments", applicationKey, PostID);
}
We then need to tell CS how to rewrite this Url so that it formats correctly; thankfully the infrastructure for this is already in place via the SiteUrls.config file; add the following element in the HomePages section:
<!-- jayson.knight fix for posting comments from feed readers -->
<url name = "weblogRssComments" location = "weblogs" path="rsscomments/{1}.aspx" pattern="rsscomments/(\d+)\.aspx" />
And finally, we need to map an httpHandler to our newly created RssCommentHandler class to intercept requests for rsscomments/*.aspx; add the following element to the httpHandlers section of the root web.config file:
<!-- jayson.knight fix for posting comments from feed readers -->
<add verb="POST" path = "rsscomments/*.aspx" type="CommunityServer.Blogs.Components.RssCommentHandler, CommunityServer.Blogs" />
Done.
I will say this about CS; it’s Url rewriting infrastructure is powerful stuff; adding a new Url is a snap with it…this would have taken much longer without this in place. Oh, and my new website is now officially done!
Sidenote: Huge thanks to Phil (aka Haacked) for helping me track down where to put the wfw:comment tag, he’s the Rss man! I really need to get better at reading RFC specs, in this case the spec located here. Thanks again Phil for your help.
Posted
Apr 19 2005, 01:37 AM
by
Jayson Knight