Oxite: Customizing the comments area
Continuing my Oxite series of blog posts I'll address the comments area. For my taste oxite is missing a couple of things on the comments listing and comments posting department. It doesn't have a way to ensure that the comment being posted is not being generated by a bot. I've already been a victim of this and to be honest I'm not a fan of SPAM, so let's stop that!

Oxite also doesn't have a special style for comments posted by the site admin. In this blog post we are going to address this issues by implementing a css class that helps the reader identify a site administrator comment from a blog comment's list and a captcha validation for the comments input.
For these tasks I'll be using css and reCAPTCHA, which is owned by google and it's widely used among popular sites as Facebook, The New York Times, StackOverflow, TicketMaster, etc. It's worth pointing out that reCaptcha was initially conceived in Carnegie Mellon University, where the term "CAPTCHA" was initially coined. The term contrives from the acronym "Completely Automated Public Turing test to tell Computers and Humans Apart."
So putting the theory to a side, let's start getting things done!
Styling the Admin comments
When the admin posts a comment Oxite automatically adds an "Admin" class to the li element from the comments list. This means that styling the comment won't be very hard since the only thing to do is add a custom style for this class. I chose a beige tone as the background of the Admin comments and added the following to the site stylesheet (site.css)
ul.comments.medium li.Admin
{
background: #FFFFC0;
}
And tha t's it, from now on my comments will have a beige like background. That was easy wasn't it? Good let's keep moving!
Implementing reCAPTCHA
Moving on to the CAPTCHA part, we have to do a couple things before starting. First register at reCAPTCHA, download the .NET dll and reference it from Oxite.Mvc project. After that the first thing to do is create an Action Filter Attribute. There's already a directory containing existing Filters for Oxite on the Oxite.Mvc project so let's place ours there.
namespace Oxite.Mvc.ActionFilters
{
public class CaptchaAttribute : ActionFilterAttribute
{
private const string ChallengeFieldKey = "recaptcha_challenge_field";
private const string ResponseFieldKey = "recaptcha_response_field";
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//Getting the user parameter from the current context
var user = (Model.User)filterContext.ActionParameters["currentUser"];
if (user != null && user.Name == "Admin")
{
filterContext.ActionParameters["captchaValid"] = true;
return;
}
var captchaChallengeValue = filterContext.HttpContext.Request.Form[ChallengeFieldKey];
var captchaResponseValue = filterContext.HttpContext.Request.Form[ResponseFieldKey];
var captchaValidtor = new Recaptcha.RecaptchaValidator
{
PrivateKey = "YOUR PRIVATE KEY GOES HERE",
RemoteIP = filterContext.HttpContext.Request.UserHostAddress,
Challenge = captchaChallengeValue,
Response = captchaResponseValue
};
var recaptchaResponse = captchaValidtor.Validate();
filterContext.ActionParameters["captchaValid"] = recaptchaResponse.IsValid;
base.OnActionExecuting(filterContext);
}
}
}
In order to render the reCAPTCHA widget we are going to add a new helper to the Html helper Extensions class. The helper is going to ease the implementation by encapsulating everything to a method call. Our new extension method should look like this:
#region ReCaptcha
public static string RenderCaptcha(this HtmlHelper helper)
{
var captchaControl = new Recaptcha.RecaptchaControl
{
ID = "recaptcha",
Theme = "clean",
PublicKey = "YOUR PUBLIC KEY GOES HERE",
PrivateKey = "YOUR PRIVATE KEY GOES HERE"
};
var htmlWriter = new HtmlTextWriter(new StringWriter());
captchaControl.RenderControl(htmlWriter);
return htmlWriter.InnerWriter.ToString();
}
#endregion
Now we are ready for the implementation. From here we just need to add our Action Filter Attribute on the Controller method that creates the post comment. The Controller is located on the same project as the Action Filers, Oxite.Mvc. The comments are created on the PostController. There we need to add our Action Filter Attribute to the AddComment method. Also we need to change the method signature by adding a new overload by adding a new variable to contain our reCAPTCHA validation result.
[CaptchaValidator]
[ActionName("Item"), AcceptVerbs(HttpVerbs.Post)]
public virtual object AddComment(Area areaInput, PostBase postBaseInput, Comment commentInput, UserBase userBaseInput,
UserBase currentUser, bool? remember, bool? subscribe, bool? captchaValid)
Now the success of the CAPTCHA validation is going to be contained on the added boolean value. Notice that the type is marked as nullable, this is because the method is initialized with null values on the OxiteApplication class.
itemActionCriteria.AddMethod(p => p.AddComment(null, null, null, null, null, null, null, null));
Great, so now we have almost everything in place. I used a quick & dirty approach in order to raise the form validation when a the introduced string does not match the one displayed by the reCAPTCHA widget. In case the captchaValid variable is false I just set the comment on the commentInput object to String.Empty. This will set the validationState object IsValid flag to false, which is Oxite's form validation mechanism.
Now the only thing left to do is go to the CommentFromAnonymous.ascx user control. This is what renders the actual comment form on the post. Here we are going to add our Html helper extension method in order to render the reCAPTCHA widget and finally add some validation to the post comment form. I decided to place my widget under the actual comment text area. The call to the extension method looks like this:
<div class="recaptcha">
<%= Html.RenderCaptcha() %>
</div>
Summary
In this blog post I added an extra, yet important, feature to Oxite: CAPTCHA validation. Once again, I was able to extend the current core with ease and added reCAPTCHA's widget. I'm so glad I did this, since I wont have to deal with spam comments anymore :). Stay tuned for some other Oxite extensions and more praising of the MVC paradigm!
2 Comments
Mr. Harry said
October 27, 2009
It's worth pointing out that reCaptcha was initially conceived in Carnegie Mellon University, where the term "CAPTCHA" was initially coined. The term contrives from the acronym "Completely Automated Public Turing test to tell Computers and Humans Apart."
===================================================================================
I never would have guessed!!
Mr. Raúl Roa said
November 04, 2009
I don't think I can say that acronym twice consecutively!