Client-side validation for two separate conditions - asp.net

Is there a way to validate asp.net text box for input using built-in validators for two distinct conditions? The text box is used in conjunction with a date picker and presently I have RegularExpressionValidator like this to validate:
<asp:TextBox ID="tbStartDate" runat="server" Width="100" CssClass="TextCompact">yyyy</asp:TextBox>
<asp:HyperLink ID="hlStartDate" runat="server" ImageUrl="~/Images/iconCalendar.gif"></asp:HyperLink><br />
<asp:RegularExpressionValidator ID="revStartDate" ControlToValidate="tbStartDate"
CssClass="TextCompact" runat="server" ErrorMessage="* Invalid Date" ValidationExpression="^(\d{4})$" />
which fires everytime an invalid date is entered - you can use the date picker or you can type in a date string.
So the issue is that I only want to validate if there is data in the text box. If the text box is empty I want it to pass through without validation.
Is this possible or would a custom client side validation be required?
Thanks,
Risho.
Update:
I've decided to write my own validator class derived from the BaseValidator class and wired it up but I get a compiler error.
namespace Abcdefg1234
{
public class Custom_Validator : BaseValidator
{
public Custom_Validator()
{
}
protected override bool EvaluateIsValid()
{
String value = this.GetControlValidationValue(this.ControlToValidate);
return ValidateControls(value.Trim());
}
public static bool ValidateControls(string value)
{
if(Regex.IsMatch(value, #"^(\d{4})$") == true)
return true;
else if(value == "")
return true;
else
return false;
}
}
}
Then I included the page directive tag:
<%# Register TagPrefix="Cv" Namespace="Abcdefg1234" TagName="CustomValidaitonX" %>
and the actual tag:
Cv:Custom_Validator ID="cvtbStartDate" ControlToValidate="tbStartDate" runat="server" ErrorMessage="* Invalid Date" />
I get a unknown server tag. Any ideas? Thanks.

The only built-in validator that fires on an empty text box would be the RequiredFieldValidator. If a textbox is empty, the other validators associated with it won't fire on form submission.
In other words, you should be fine just as you are, with the RegularExpressionValidator not firing if you submit with the textbox still empty. Are you experiencing different behavior?
ETA: You need to specify the Assembly name in your Register page directive for the Custom_Validator to be recognized. I don't believe the tag name is required for a custom control.

Related

Is it possible to add logic to influence the way RequiredFieldValidator behaves?

I have added textbox on the page that Jquery to create a datepicker. The problem is that, the textbox doesn't hold the value after a postback. After researching, I found the following solution which works perfectly, i.e. the textbox keeps its value after a postback.
<th>
<asp:CustomValidator ID="customStartDate" runat="server"
ErrorMessage="Start Date" Display = "None" ControlToValidate = "txtStartDate"
ValidationGroup ="HireGroup" ClientValidationFunction ="StartDate_Validate"/>
Start Date:
</th>
<td>
<asp:TextBox ID="txtStartDate" runat="server" Width = "140" ReadOnly = "true"
TabIndex = "5" CssClass = "datepicker" ></asp:TextBox>
<asp:HiddenField ID="hfDatePicker" runat="server"/>
</td>
And this is the Jquery code
//Set datePicker
function SetUpDatePicker() {
var $allDatepickers = $('.datepicker');
$.each($allDatepickers, function () {
$(this).datepicker({
showOn: "button",
buttonImage: "Images/calendar.gif",
buttonImageOnly: true,
minDate: 1,
altField: '[id*="hfDatePicker"]'
});
var $hfDatePicker = $('[id*="hfDatePicker"]');
var val = $($hfDatePicker).attr('Value');
$(this).val(val);
var len = $($hfDatePicker).attr('Value').length;
if (len > 0) {
$(this).datepicker("setDate", new Date($($hfDatePicker).attr("Value")));
}
});
}
Now I have a different type of problem. I can't use a RequiredFieldValidator for a HiddenField as I am getting an error "Hidden Field cannot be validate".
I'm tryind a CustomValidator, but the problem is that this control does acts only when the ControlToValidate is not empty.
I've checked all the property for RequiredFieldValidator and don't see something like ClientValidationFunction property.
Any suggestion on how to solve that problem?
(Based on the comment by #Richard77, I will make this an actual answer.)
You have a several options...
Instead of using a <asp:Hidden>, use a normal <asp:TextBox> but hide it using style='display:none; attribute. This will allow you to use the <asp:RequiredFieldValidator> as per your needs.
Another way to do it is using the <asp:CustomValidator> and add the ValidateEmptyText='true' attribute. This will force the validator to run the code even when the TextBox is empty.
Update - after thinking about this, I would NOT recommend the following, because it's not possible (that I can think of) to override the server-side version of the function, and therefore will leave you open to vulnerabilities. It's fine to do if you're purely using it for say visual reasons, and don't need the actual data to be checked on the server - however, this is an unusual situation.
A final option (but not one that I would necessarily recommend) is to override the function generated by ASP.NET. This would need to be placed on your page somewhere after the script link generated by ASP.NET, something like...
function RequiredFieldValidatorEvaluateIsValid(val) {
if(val.controltovalidate=="myValidatorId"){
// your coding here
} else {
return (ValidatorTrim(ValidatorGetValue(val.controltovalidate)) != ValidatorTrim(val.initialvalue))
}
}

Showing single error for multiple asp validators

I have a text box control in asp with 3 different validators. Each validator is getting its error message from the server, and each one validates different things.
My problem is that for some values, two or more validators are firing and I'm getting more then one error message.
I would like to make some kind of priority functionality, meaning that if the first validator is firing the other two will not. Is there any way to make the validator behave like that?
I've added some code sample:
<asp:RequiredFieldValidator ID="cvRequired" runat="server" Display="Dynamic"
ControlToValidate="txtBox" />
<asp:RegularExpressionValidator ID="cvFormat" runat="server" Display="Dynamic"
ControlToValidate="txtBox" ValidationExpression="^([A-Za-z])+$" />
<asp:CustomValidator ID="cvCustom" runat="server" Display="Dynamic"
ControlToValidate="txtBox" ClientValidationFunction="validateFunction" />
I want that the format validator and the custom validator will not fire if the required validator is invalid (actually, I just want them to not showing their error message).
As I said, the error messages are from the server, so I can't really join them to one custom validator. Also, the "validateFunction" is in another js file (for re-use).
Few logic options you got to think about,
(txtPhone) having three validators.
1.RangeValidator, 2.CustomValidator 3.Regexvalidator
Say,after validation (check what it returns if validation fails/passes) and act upon that.
if(rangevalidator1 != null)
{
...somecode...
}
I ll suggest you using javascript ..
you can use a single custom validator for all three validation and you put your code in if condition according to your need.
<asp:CustomValidator runat="server" ID="cstmStartDateValidater"
ToolTip="Start date cannot be greater than equal to end date/time or less than current date/time"
ErrorMessage="*" ControlToValidate="txtStartDateTime"
ForeColor="Red" ValidationGroup="vlgMessage" SetFocusOnError="true"
onservervalidate="cstmStartDateValidater_ServerValidate" ></asp:CustomValidator>
in the .cs page
protected void cstmStartDateValidater_ServerValidate(object source, ServerValidateEventArgs args)
{
if (CompareStartDate())
{
args.IsValid = true;
}
else
{
args.IsValid = false;
}
}
you can use following link for more information :
MSDN,
Code Project
hope these will help you .
Make use of ValidatorCalloutExtender control which is available in ajax control toolkit.
Place a separate ValidatorCalloutExtender across each control,you wish to validate it.

How can i turn off ASP.NET required field validator "lost focus" behaviour

I have some code where I need two separate required field validators for one control, both in separate validation groups which are then validated by two separate buttons.
This approach works well when the buttons are clicked but both validators show if I enter a value in the textbox and then remove it.
Is there a way to turn this"lost focus" validation off? I only need it to validate when the buttons are clicked.
EDIT
Unfortunately, if I set EnableClientScript=false then I dont have any client notifications. What I want is for the dynamic error message to show (effectivly in the OnClientClick event of the button) but not the "lost focus" of the textbox.
Is there some way I can disable or "unhook" the lostfocus client event?
EDIT
A combination dDejan's answer and womp's answeer here sorted the problem perfectly.
My final code looks like this (for anyone else with a similar situation)...
Javascript...
<script type="text/javascript">
$(document).ready(function() {
$('body').fadeIn(500);
//Turn off all validation = its switched on dynamically
$.each(Page_Validators, function(index, validator) {
ValidatorEnable(validator, false);
});
});
function ToggleValidators(GroupName) {
$.each(Page_Validators, function(index, validator) {
if (validator.validationGroup == GroupName) {
ValidatorEnable(validator, true);
} else {
ValidatorEnable(validator, false);
}
});
}
</script>
ASPX Control Example...
<telerik:RadTextBox Width="196px" ID="txtFirstName" runat="server" MaxLength="50" Skin="Black"></telerik:RadTextBox>
<asp:RequiredFieldValidator ID="valFirstName" CssClass="Validator" runat="server" EnableClientScript="true" Display="Dynamic" ErrorMessage="You must enter your first name." ControlToValidate="txtFirstName" ValidationGroup="NeededForEmail"></asp:RequiredFieldValidator>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" CssClass="Validator" runat="server" EnableClientScript="true" Display="Dynamic" ErrorMessage="You must enter your first name." ControlToValidate="txtFirstName" ValidationGroup="NeededForSubmit"></asp:RequiredFieldValidator>
ASPX Button Code...
<asp:Button ID="btnGetConfCode" runat="server" Text="Get Confirmation Code" OnClientClick="ToggleValidators('NeededForEmail')" OnClick="btnGetConfCode_Click" Width="100%" ValidationGroup="NeededForEmail"/>
<asp:Button ID="btnRegisterUser" runat="server" Text="Register" OnClientClick="ToggleValidators('NeededForSubmit')" OnClick="btnRegisterUser_Click" Width="100px" ValidationGroup="NeededForSubmit" />
So, now there is no validation until a user clicks either the "Get Email Confirmation Code" button or the "Register" button.
If they click the "Get Email Confirmation Code" button all of the controls validate apart from the textbox where the user is to input the email validation code and we only see one validator message.
If they click the "Register" Button then all of the controls validate and we only see one validation message.
If either button is pressed, the user goes back, adds and then removes some text then we only see one validator. Before this change you used to see both messages saying the same thing.
Thank you for help guys
You can set if the validators are "active" or not with client side code using the ValidatorEnable function. Basically it goes like this
var validator = document.getElementById('<%=Validator1.ClientID%>');
ValidatorEnable(validator , state); //where state is boolean
You can also trigger the validator to validate on some event (like for example the click of the buttons) using the ValidatorValidate(validator) function.
I am not sure which would work better for you (enabling/disabling the validators or custom triggering of the validation) but I suggest this article that will guide you in the right direction
ASP.NET Validation in Depth
There's no way to unhook them if EnableClientScript=true.
What you could do is set it to false. Then create a javascript validation method that is called on your submit-button onClientClick event.
In your method, you would have to call ValidatorValidate(control) for each control you want to validate client side
There's an example here:
http://msdn.microsoft.com/en-us/library/Aa479045#aspplusvalid_clientside
You could turn off the javascript validation by setting EnableClientScript="false" that would get rid of the lost focus validation.
You can use Custom Validator controls instead and either validate the input using Javascript on the client or within the event handler on the server. Ensure you set ValidateEmptyText="true" on the validation controls otherwise the events will not fire on an empty field.
Try to Enable on Both button click using javascript and disable it on textbox blur event.
Try resetting the onchange event for the input-control.
$(document).ready(function () {
$("#controlid").each(function () { this.onchange = null; })
});
var validator = document.getElementById('<%=Validator1.ClientID%>');
ValidatorEnable(validator , state);
It is working in javascript but when we use the page.Isvalid function on Server side it creates the problem to check page is valid or not.
simply type this code in page_load event
textboxname.Attributes.Add("onblur","ValidatorOnChange(event);");

Elegant way to make CustomValidator work with ValidationSummary messagebox

I have run into this problem before but never quite solved it. I have a form with several validators and also a CustomValidator.
<asp:Label ID="lblMemberNum" runat="server" Text="Membership #:" CssClass="LabelMedium" ></asp:Label>
<asp:TextBox ID="txtMemberNum" runat="server" CssClass="TextBox" ></asp:TextBox>
<asp:RequiredFieldValidator ID="rfvMemberNum" SetFocusOnError="True" runat="server"
ControlToValidate="txtMemberNum" ErrorMessage="[ Membership # ] is required"
CssClass="ValidationMessage" Display="Dynamic" >*</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="revMemberNum" Display="Dynamic" runat="server"
ControlToValidate="txtMemberNum" CssClass="ValidationMessage"
ErrorMessage="[ Membership # ] can only contain letters"
ValidationExpression="^([a-zA-Z\d]+)$" >*</asp:RegularExpressionValidator>
<asp:CustomValidator ID="cvMemberNum" runat="server"
CssClass="ValidationMessage" Display="Dynamic"
ControlToValidate="txtMemberNum" ValidateEmptyText="false"
OnServerValidate="cvMemberNum_Validate"
ErrorMessage="This membership number is already registered">*</asp:CustomValidator>
<asp:ValidationSummary ID="ValidationSummary1" runat="server"
CssClass="ValidationMessage"
ShowMessageBox="True" ShowSummary="False" />
and on the server side:
protected void cvMemberNum_Validate(object source, ServerValidateEventArgs args)
{
try
{
args.IsValid = (!CampaignRegistration.IsMemberRegistered(args.Value));
}
catch
{
args.IsValid = false;
}
}
My problem is: The ValidationSummary never shows the message from CustomValidator. This question has been asked in several places, but I havent seen a satisfactory answer.
Try using a ValidationGroup property across all your validators and the ValidationSummary.
EDIT: Another possibility could be the Server Validation Code
args.IsValid = (!CampaignRegistration.IsMemberRegistered(args.Value));
if CampaignRegistration.IsMemberRegistered(args.Value) is returning false, "!" is making it true and therefore making it valid. I think you should get rid of the "!" as follows:
args.IsValid = CampaignRegistration.IsMemberRegistered(args.Value);
UPDATE: In order for the ValidationSummary to display your custom validator message in a messagebox, you need to have ClientValidationFunction Code. If you need to display just the summary without a popup, this is not needed.
<asp:CustomValidator ID="cvMemberNum" runat="server"
CssClass="ValidationMessage" Display="Dynamic"
ControlToValidate="txtMemberNum" ValidateEmptyText="false"
OnServerValidate="cvMemberNum_Validate"
ClientValidationFunction = "ClientValidate"
ErrorMessage="This membership number is already registered">*</asp:CustomValidator>
//JavaScript Code.
function ClientValidate(source, args)
{
args.IsValid = false; //you need to add validation logic here
}
MORE: If you don't want to do ClientSide Validation, try this trick to show the alert. Make this change to your CustomValidator ServerValidate method:
protected void cvMemberNum_Validate(object source, ServerValidateEventArgs args)
{
bool isValid = true;
try
{
isValid = (!CampaignRegistration.IsMemberRegistered(args.Value));
}
catch
{
isValid = false;
}
args.IsValid = isValid;
if(!isValid)
{
if(!Page.IsClientScriptBlockRegistered("CustomValidation"))
Page.RegisterClientScriptBlock("CustomValidation", "<script>alert('This membership number is already registered');</script>");
}
}
The ShowMessageBox option is fully client-side, so it will only evaluate if you have set the ClientValidationFunction on the CustomValidator.
You can also fake it by registering a script that makes an alert, so when you get back from the server's validation, it'll prompt with the error message. This can either be registered in the ServerValidate method (per #Jose Basilio), or you can call the following method during the PreRender event to register a popup with all invalid validators on the page:
/// <summary>
/// Registers a script to display error messages from server-side validation as the specified <see cref="UserControl"/> or <see cref="Page"/> loads from a postback.
/// </summary>
/// <remarks>
/// Must be called in the PreRender if used to validate against the Text property of DNNTextEditor controls, otherwise Text will not be populated.
/// Must set the ErrorMessage manually if using a resourcekey, otherwise the resourcekey will not have overridden the ErrorMessage property.
/// </remarks>
/// <param name="ctrl">The <see cref="UserControl"/> or <see cref="Page"/> which is being posted back.</param>
/// <param name="validationGroup">The validation group against which to validate.</param>
public static void RegisterServerValidationMessageScript(TemplateControl ctrl, string validationGroup)
{
if (ctrl != null && ctrl.Page.IsPostBack)
{
ctrl.Page.Validate(validationGroup);
if (!ctrl.Page.IsValid)
{
StringBuilder errorMessage = new StringBuilder("<script language='javascript'>alert('");
for (int i = 0; i < ctrl.Page.Validators.Count; i++)
{
IValidator validator = ctrl.Page.Validators[i];
if (!validator.IsValid)
{
errorMessage.Append("- " + validator.ErrorMessage);
if (i < ctrl.Page.Validators.Count - 1)
{
errorMessage.Append(#"\r\n");
}
}
}
errorMessage.Append("');</script>");
ctrl.Page.ClientScript.RegisterStartupScript(typeof(IValidator), "validationAlert", errorMessage.ToString(), false);
}
}
}
I've recently had same problem. ValidationSummary was not showing the ErrorMessage from CustomValidator when ServerValidate stated validation failure. Since by default (as my little reverse engineering showed) validation summary is rendered client side on postback I've simply added a script that checks all validators on document load/async postback completion and triggers validation summary creation for failed validation groups:
$(document).ready(function () {
var displayAlert = function () {
if (typeof Page_Validators == 'undefined') return;
var groups = [];
for (i = 0; i < Page_Validators.length; i++)
if (!Page_Validators[i].isvalid) {
if (!groups[Page_Validators[i].validationGroup]) {
ValidationSummaryOnSubmit(Page_Validators[i].validationGroup);
groups[Page_Validators[i].validationGroup] = true;
}
}
};
displayAlert();
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(
function () {
displayAlert();
});
}
);
In my scenario I had nested user controls with validators, update panel and validation summary at the parent page.
More details here.
You should write a property
ValidationGroup="ValidationSummary1"
at every validator in your case.
Also check if your page has
AutoEventWireup="true"
bduke's RegisterServerValidationMessageScript is "faking it", but it isn't. It really fixes the problem. Every Utility namespace needs this function somewhere.
I have found a workaround for when javascript is disabled and the ValidationSummary does not show the errorMessage property of the CustomValidator. This is required as injecting script or alerts, as described above, will not work.
Add a new Validator control, let's call it CustomValidatorProxy, set its ControlToValidate property to any one of the controls on the form and EnableClientScript=false.
Within the ServerValidate event handler perform your custom validation and if validation fails set the IsValid property of the CustomValidator and CustomValidatorProxy to false and similarly set both ErrorMessage properties.
If the validation in the ServerValidate is passed ensure that the IsValid property of the CustomValidatorProxy is set to true.
Provided the CustomValidatorProxy is before the CustomValidator in the ValidatorCollection of the Page then the ServerValidate handler will override the IsValid property value that the CustomValidatorProxy would have returned having validated the ControlToValidate value and your ErrorMessage from your CustomValidator will be displayed in the ValidationSummary.
This worked for me:
<asp:CustomValidator runat="server" ID="cv"
ClientValidationFunction="ValidateFunction"
ErrorMessage="Default error
message">*</asp:CustomValidator>
<script type="text/javascript">
function ValidateFunction(sender, args)
{
var msg ='';
var formValid = true;
[various checks setting msg and formValid]
if (msg.length > 0) { sender.errormessage = msg; }
args.IsValid = formValid;
}
</script>

asp.net - gridview validation - repeating validation messages issue

I have a gridview that contains one to many rows (like most do) - each with an input textbox. Each row has a requiredfieldvalidator against that textbox. When the form is submitted the gridview is validated it is entirely possible that more than one row has an empty textbox. This results in repeating validation messages e.g.
Please provide text for 'Name' field
Please provide text for 'Name' field
Please provide text for 'Name' field
Is it possible to consolidate these messages into one message?
I know it possible to create a validator by setting up a validator class and inheriting from BaseValidator class which can be used to validate the gridview as a whole. But I put an image against each row when it is invalid so I should imagine I require separate validators on each row.
This is a solution that uses a CustomValidator and requires a few organizational changes. This requires a postback since CustomValidator validation is performed on the server-side.
Here's the setup:
For each of your existing RequiredFieldValidators that display the "Please provide text for 'Name' field" message you will need to set:
EnableClientScript="false"
ValidationGroup="vgTxtName" (provide your own name)
ErrorMessage="" (or remove it altogether; the CustomValidator will now be responsible for this)
You have the option of displaying nothing at all (less clear to the user) or displaying an asterisk to indicate which validator is invalid.
Option 1:
Display="None"
Option 2 (preferred):
Display="Dynamic"
Set the text in between the validator tags to: *
No changes needed for your ValidationSummary control (it should be neutral and not have a ValidationGroup attribute set, which is the default)
Add a CustomValidator (see code below)
Add an eventhandler for the CustomValidator's ServerValidate event (you can just double click it from the designer to have it generated)
Implement the eventhandler logic (see code below)
The idea is not to directly allow the page to handle those RequiredFieldValidators anymore and instead we'll let the CustomValidator do it.
TextBox RequiredFieldValidator example (you should have something that looks like this with relevant ID names which corresponds to step 1 above):
Option 1:
<asp:RequiredFieldValidator ControlToValidate="txt1" ID="rfv1" runat="server"
EnableClientScript="false" Display="None" ValidationGroup="vgTxtName" />
Option 2:
<asp:RequiredFieldValidator ControlToValidate="txt1" ID="rfv1" runat="server"
EnableClientScript="false" Display="Dynamic" ValidationGroup="vgTxtName">*
</asp:RequiredFieldValidator>
CustomValidator Markup (you can place this anywhere sensible, such as next to the ValidationSummary control):
<asp:CustomValidator ID="cvName" runat="server" Display="None"
ErrorMessage="Please provide text for 'Name' field"
OnServerValidate="cvName_ServerValidate" />
The error message here replaces the ones from the individual validators. Also notice there's no ControlToValidate set, which is valid for this type of validator and is useful for applying validation covering multiple controls.
CustomValidator EventHandler (cvName_ServerValidate):
protected void cvName_ServerValidate(object source, ServerValidateEventArgs args)
{
// Validate vgTxtName group
Page.Validate("vgTxtName");
// .NET 3.5 - add using System.Linq;
args.IsValid = Page.GetValidators("vgTxtName")
.OfType<RequiredFieldValidator>()
.All(v => v.IsValid);
// .NET 2.0 (use either this or the above, not both)
bool isValid = true;
foreach (RequiredFieldValidator validator in Page.GetValidators("vgTxtName"))
{
isValid &= validator.IsValid;
}
args.IsValid = isValid;
}
That's it! Just bear in mind that this is strictly for RequiredFieldValidators. You shouldn't place different types of validators in the "vgTxtName" group since the cvName logic deals strictly with the RequiredFieldValidator type. You'll need to setup different groupings or tweak the code if you intend to use other validator types.
I would suggest not using a Validator Summary.
Change the Text property or inner content of the validators to something more appropriate for your application.
For example...
<asp:Validator ID="X" ... runAt="server" Text="*" />
or
<asp:Validator ID="X" ... runAt="server">*</asp:Validator>
or to display an image...
<asp:Validator ID="X" ... runAt="server"><img src="../path.png" alt="Invalid" /></asp:Validator>
I also style the validator to change to pointer to the help cursor and add a ToolTip property to show the same Error Message.

Resources