Hi, I created a custom captch fieldtype using MSCaptcha. The custom control seems to be working fine in a normal .aspx page, but it's not working when it's within contour form page. I added a custom validator to validate the captcha text, the validation works fine but the form is not submitting even though the page is valid. I wonder if there's anything wrong my fieldtype? Any help would be appreciated. Thanks.
Here is the code for my custom captcha control:
using System; using System.Collections.Generic; using System.Linq; using System.Web.UI; using System.Web.UI.WebControls; using MSCaptcha;
namespace Model.Forms.Controls { public class Captcha : TextBox { public CaptchaControl CaptchaControl { get { EnsureChildControls(); return this.captcha; } set { this.captcha = value; } }
/// <summary> /// get find control method using generics /// </summary> /// <typeparam name="T">type of item you want</typeparam> /// <param name="ancestor">parent to start looking from</param> /// <returns>collection of T items</returns> public List<T> ControlsByTypeUsingAncestor<T>(Control ancestor) where T : Control { var controls = new List<T>();
//Append to search results if we match the type if (typeof(T).IsAssignableFrom(ancestor.GetType())) { controls.Add((T)ancestor); }
//Recurse into child controls foreach (Control ctrl in ancestor.Controls) { controls.AddRange(ControlsByTypeUsingAncestor<T>(ctrl)); }
return controls; } } }
And my custom field type:
using System; using System.Collections.Generic; using System.Web.UI.WebControls; using Umbraco.Forms.Core;
namespace Model.Forms.FieldTypes { public class Captcha : FieldType { public Controls.Captcha CaptchaControl;
public List<object> Value;
public Captcha() { base.Id = new Guid("F8C089B9-7D8F-47B0-A594-9FD9903FBF42"); base.Name = "Captcha"; base.Description = "Renders a Captcha"; this.Icon = "textfield.png"; this.DataType = FieldDataType.String; this.Value = new List<object>();
this.CaptchaControl = new Controls.Captcha(); }
public override WebControl Editor { get { return this.CaptchaControl; } set { base.Editor = value; } }
public override List<object> Values { get { if (!string.IsNullOrEmpty(this.CaptchaControl.Text)) { this.Value.Clear(); this.Value.Add(this.CaptchaControl.Text); } return this.Value; } set { this.Value = value; } }
public override bool SupportsPrevalues { get { return false; } }
public override bool SupportsRegex { get { return false; } }
Sorry to drag up an old thread, but I have a requirement for the same functionality as the above. I have found the source of your problem, but not a solution.
The problem is that the captchaVal_ServerValidate event seems to be firing twice. The first time it validates successfully, however the second time it runs, the ValidateCaptcha() throws an exception and hence the catch returns false.
I have implemented a workaround, but it's so hacky and I'm not proud that I'm not even going to post the code here!
custom field type not saving
Hi, I created a custom captch fieldtype using MSCaptcha. The custom control seems to be working fine in a normal .aspx page, but it's not working when it's within contour form page. I added a custom validator to validate the captcha text, the validation works fine but the form is not submitting even though the page is valid. I wonder if there's anything wrong my fieldtype? Any help would be appreciated. Thanks.
Here is the code for my custom captcha control:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using MSCaptcha;
namespace Model.Forms.Controls
{
public class Captcha : TextBox
{
public CaptchaControl CaptchaControl
{
get
{
EnsureChildControls();
return this.captcha;
}
set
{
this.captcha = value;
}
}
private CaptchaControl captcha;
private CustomValidator captchaVal;
protected override void OnInit(EventArgs e)
{
string vGroup = string.Empty;
List<RequiredFieldValidator> reqValidators = this.ControlsByTypeUsingAncestor<RequiredFieldValidator>(this.Page);
if (reqValidators != null)
{
var validatorWithGroupSet = (from v in reqValidators
where v.ValidationGroup != string.Empty
select v);
if (validatorWithGroupSet != null)
vGroup = validatorWithGroupSet.FirstOrDefault().ValidationGroup;
}
this.captcha = new CaptchaControl();
this.captcha.CaptchaBackgroundNoise = CaptchaImage.backgroundNoiseLevel.Low;
this.captcha.NoiseColor = System.Drawing.Color.FromArgb(251, 194, 196);
this.captcha.CaptchaLength = 4;
this.captcha.CaptchaHeight = 60;
this.captcha.CaptchaWidth = 250;
this.captcha.CaptchaLineNoise = CaptchaImage.lineNoiseLevel.None;
this.captcha.CaptchaMinTimeout = 5;
this.captcha.CaptchaMaxTimeout = 240;
base.CssClass = "text";
this.captchaVal = new CustomValidator();
this.captchaVal.ErrorMessage = "Invalid code";
this.captchaVal.ServerValidate += new ServerValidateEventHandler(captchaVal_ServerValidate);
this.captchaVal.IsValid = true;
this.captchaVal.Display = ValidatorDisplay.Dynamic;
this.captchaVal.ValidateEmptyText = true;
this.captchaVal.EnableClientScript = false;
this.captchaVal.CssClass = "contourError";
if (!string.IsNullOrEmpty(vGroup))
{
base.ValidationGroup = vGroup;
this.captchaVal.ValidationGroup = vGroup;
}
base.Controls.Add(this.captchaVal);
base.Controls.Add(this.captcha);
}
void captchaVal_ServerValidate(object source, ServerValidateEventArgs args)
{
try
{
args.IsValid = ValidateCaptcha();
}
catch
{
args.IsValid = false;
}
}
private bool ValidateCaptcha()
{
bool flag = true;
if (this.captcha != null)
{
if (string.IsNullOrEmpty(base.Text))
{
flag = false;
}
else
{
this.captcha.ValidateCaptcha(base.Text);
flag = this.captcha.UserValidated;
}
}
else
{
flag = false;
}
if (flag)
this.captchaVal.Style.Add("display", "none");
else
this.captchaVal.Style.Add("display", "block");
return flag;
}
protected override void Render(HtmlTextWriter writer)
{
base.RenderChildren(writer);
base.Render(writer);
}
/// <summary>
/// get find control method using generics
/// </summary>
/// <typeparam name="T">type of item you want</typeparam>
/// <param name="ancestor">parent to start looking from</param>
/// <returns>collection of T items</returns>
public List<T> ControlsByTypeUsingAncestor<T>(Control ancestor) where T : Control
{
var controls = new List<T>();
//Append to search results if we match the type
if (typeof(T).IsAssignableFrom(ancestor.GetType()))
{
controls.Add((T)ancestor);
}
//Recurse into child controls
foreach (Control ctrl in ancestor.Controls)
{
controls.AddRange(ControlsByTypeUsingAncestor<T>(ctrl));
}
return controls;
}
}
}
And my custom field type:
using System;
using System.Collections.Generic;
using System.Web.UI.WebControls;
using Umbraco.Forms.Core;
namespace Model.Forms.FieldTypes
{
public class Captcha : FieldType
{
public Controls.Captcha CaptchaControl;
public List<object> Value;
public Captcha()
{
base.Id = new Guid("F8C089B9-7D8F-47B0-A594-9FD9903FBF42");
base.Name = "Captcha";
base.Description = "Renders a Captcha";
this.Icon = "textfield.png";
this.DataType = FieldDataType.String;
this.Value = new List<object>();
this.CaptchaControl = new Controls.Captcha();
}
public override WebControl Editor
{
get
{
return this.CaptchaControl;
}
set
{
base.Editor = value;
}
}
public override List<object> Values
{
get
{
if (!string.IsNullOrEmpty(this.CaptchaControl.Text))
{
this.Value.Clear();
this.Value.Add(this.CaptchaControl.Text);
}
return this.Value;
}
set
{
this.Value = value;
}
}
public override bool SupportsPrevalues
{
get
{
return false;
}
}
public override bool SupportsRegex
{
get
{
return false;
}
}
public override string RenderPreview()
{
return "<img src=\"/Images/layout/capex.jpg\" alt=\"captcha\" /><br /><input type=\"text\" class=\"textfield\" />";
}
public override string RenderPreviewWithPrevalues(List<object> prevalues)
{
return this.RenderPreview();
}
}
}
Hi iWuha,
Sorry to drag up an old thread, but I have a requirement for the same functionality as the above. I have found the source of your problem, but not a solution.
The problem is that the captchaVal_ServerValidate event seems to be firing twice. The first time it validates successfully, however the second time it runs, the ValidateCaptcha() throws an exception and hence the catch returns false.
I have implemented a workaround, but it's so hacky and I'm not proud that I'm not even going to post the code here!
Did you ever get this working correctly?
Andrew
is working on a reply...