asp:CustomValidator not returning 'false' - asp.net

Don't know what is wrong here. This is a page developed by someone else and I am trying to fix one of the issue.
Scenario:
ASP.NET site.
Login.aspx has <asp:login> and there are three validation groups.
Login.aspx.cs is a partial class of "user_login".
Each validation group has a textbox and an associate customvalidator. All three custom validators gets triggered when something is entered in corresponding textbox but issue is only the first textbox (bound to validationgroup = 1) returns false when validation fails.
For 2nd and 3rd, the customvalidator get triggered but when there is validation issue and even after setting "args.IsValid = false;", the process continues with what needs to be executed further.
Don't know what is going on wrong here. I would like the customvalidator to return false. Worst case, are there any ways to return the control back to the 'textbox' when validation fails?
Below is the custom validator used.
<asp:CustomValidator ID="ExistingIdValidator" runat="server" ControlToValidate="NewUserName"
ValidateEmptyText="true" ValidationGroup="NewUserForm"
OnServerValidate="NewUserNameCheck_ServerValidate">
</asp:CustomValidator>
protected void NewUserNameCheck_ServerValidate(object source, ServerValidateEventArgs args)
{
CustomValidator validator = source as CustomValidator;
if (validator != null)
{
string NewuserNameValue = this.NewUserName.Text;
Guid registeredUserId = (Guid)Membership.GetUser(NewuserNameValue).ProviderUserKey;
if (registeredUserId != null)
{
validator.IsValid = false;
this.FailureText_New.Text = "This UserID already exists. Please login as existing user";
args.IsValid = false;
}
}
}

The funny thing about ASP.NET server-side validation is that it does not automatically prevent your click events from executing. It's as if the validation procedure is performed and then the results are ignored. So, the first thing to put inside your button's event is if (!Page.IsValid) return;. That's how you prevent the rest of the event from executing, and that's how you force the user to correct any mistakes on the form.

Related

validation step by step

I have an aspx page with three textbox controls, and i want to do validation for all.
i want to show the error message in a sequence,
for example if i left all three text boxes empty and click on submit button,
first it will show error message for first text box and then when i fill the first textbox and click again save then it shows the error message for the second textbox and so on.
that means i only want to show one error message at a time after clicking the submit button.
can you people suggest me the way.
You could do it though checking on submission of the form and posting back to a literal with error messages. Postback validation is better than just relying on javascript in any case.
So, depending on the level of checks you want to employ, you could do something like:
protected void btnSubmit_Click(object sender, eventArgs e)
{
if(String.IsNullOrEmpty(txtBox1.Text))
{
ltError.Text = "Sorry, error message for box1";
return;
}
}
Obviously you'd work in more checks and after passing stage1 you'd move on to stage 2. Not great from a user experience but would work.
you can return a function value like this
public string CheckValidation()
{
if (txtFirstName.Text.Trim().Equals(string.Empty))
return "Please enter firstname";
if (txtLastName.Text.Trim().Equals(string.Empty))
return "Please enter lastname";
}
and so on as per your validation fields.
Hope this helps you
Can you use the AJAX control toolkit? The VaidatorCallout controls behave this way and you get a nice little balloon indicating where the error is.
ASP.NET Validator Callout
I'd recommend an <asp:CustomValidator> control for each textbox. You can use something like the following for the custom validation routines:
var textBox1IsValid = function textBox1IsValid(sender, args) {
var tb = document.getElementById('TextBox1'),
resultOfValidation = false;
//do validation, modifying resultOfValidation as needed.
arg.IsValid = resultOfValidation;
return resultOfValidation;
},
textBox2IsValid = function textBox2IsValid(sender, args) {
var tb = document.getElementById('TextBox2'),
resultOfValidation = false;
//do validation, modifying resultOfValidation as needed.
//return either the validity of TextBox2
//or (if TextBox1 is not valid) return true so the
//validator for TextBox2 doesn't fire.
arg.IsValid = resultOfValidation || !textBox1IsValid(sender, args);
return resultOfValidation;
},
textBox3IsValid = function textBox3IsValid(sender, args) {
var tb = document.getElementById('TextBox3'),
resultOfValidation = false;
//do validation, modifying resultOfValidation as needed.
//return either the validity of TextBox3
//or (if either TextBox1 or TextBox2 is not valid) return
//true so the validator for TextBox3 doesn't fire.
arg.IsValid = resultOfValidation || !textBox1IsValid(sender, args) || !textBox2IsValid(sender, args);
return resultOfValidation;
};
The advantage of this approach is that TextBox2 and TextBox3 will return as valid if their contents are valid or if TextBox1 is not valid. This will fire only one validator at a time, until all fields are valid. It's also a little more flexible as your custom validation routine can check for:
required field
pattern matching
value comparison
or any other validation that you need, all wrapped up into one function.
The downside is that you'll also need to duplicate the validation logic server-side.

Differential validation of a textbox in asp.net webforms

I am working on an asp.net webforms project. I have a usercontrol with a boolean public property, named as IsRequired, which can be set either to true or false. I have a text box where the user will enter the social security number (SSN). If IsRequired = true, then the user has to enter the SSN value, otherwise validation should fail and "SSN is required" message should be displayed next to the textbox. If IsRequired = false, then if the user doesn't enter a SSN value, then a messagebox should be displayed with the message, "If you have a SSN, please enter it". Essentially the message encourages the suer to enter SSN. If the click "OK" on the messagebox, then they could enter the value. otherwise they could submit the page, and the validation should not fail.
I am using DevExpress controls, and came up with the following solution:
on ascx page:
<dx:ASPxTextBox ID="SsnTextBox" runat="server" OnValidation="SocialSecurity_Validation">
<MaskSettings Mask="999999999"></MaskSettings>
</dx:ASPxTextBox>
on the codebehind:
if (IsSubscriber && (e.Value == null || (string)e.Value == ""))
{
SsnTextBox.ErrorText = "Required";
e.IsValid = false;
}
else if (!IsSubscriber && (e.Value == null || (string)e.Value == ""))
{
e.IsValid = true;
Page.ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "UserControl",
"confirm('If Social Security Number is available, please enter it!')", true);
}
The problem with the code it works only partially. For example, the message box is displayed, but when either ok or cancle is clicked, the page is posted without giving the option to enter a value. If IsRequired = true, and a value is not entered, validation fails, still the page gets submitted. Any help to resolve this or a better code is appreciated. The solution need not be DevExpress specific, instead it could a generic one.
Thanks
Rather than use the confirm method; which will return either a true or false depending on what the user selects, why not use Alert() instead?
I.E
return Alert('If Social Security Number is available, please enter it!')
There won't be a choice for the user - just an OK button. 'return' will also prevent the postback.

Conditional Validation ASP.NET

I have 2 TextBoxes (textBoxA, textBoxB), both watched by their own RequiredFieldValidator. I want to 'enable' the RequiredFieldValidator for textBoxB just when textBoxA has a value (or meets some specific conditions).
Use cases:
Case 1
textBoxA = ""; -> Show Required Field Validation Message
textBoxB = ""; -> Do not show validation message
Case 2
textBoxA = "has a value";
textBoxB = ""; -> Show Required Field Validation Message
Case 3
textBoxA = "has a value";
textBoxB = "has a value too";
Thanks for your help!!
You might want to use a CustomValidator to do this. You'll need to implement the client side and server side validation. Something like (off the top of my head and untested)
Server side
protected void ServerValidation (object source, ServerValidateEventArgs args)
{
if (!string.IsNullOrEmpty(textBoxA))
args.IsValid = !string.IsNullOrEmpty(textBoxB);
}
Client Side
function clientValidation(sender, args) {
if (args.value !== "") {
var textBoxB= document.getElementById('textBoxB');
args.IsValid = (textBoxB.value !== "");
}
return;
}
In this situation I'd use a CustomValidator for textBoxB instead of the required field validator. In the server side validation method you can control the exact nature of the validation with something like this.
if (textBoxA.Text != string.Empty)
{
args.IsValid = textBoxB.Text != string.Empty;
}
I don't believe there's a declarative way to do it. I've always done this by having a ValidatePage method where I set my validators to enabled or disabled and then call Page.Validate at the end (and then proceed or render based on Page.IsValid).
So, either
validator2.IsEnabled = textBoxA.Text.Trim().Length > 0
or something like that.
That's pseudo code btw...I haven't done ASP.NET in some time now.
What I do is to change the Validation Group according to requirement, for example, you may assign the validation group to the textBoxB to a value different or the same that textBoxA.ValidationGroup & the submit control, this may be done in textBoxB's Onchange.
Validators which are evaluated are all that correspond to the same validation group of the submit control.

Programmatically add UserControl with events

I need to add multiple user controls to a panel for further editing of the contained data. My user control contains some panels, dropdown lists and input elements, which are populated in the user control's Page_Load event.
protected void Page_Load(object sender, EventArgs e)
{
// populate comparer ddl from enum
string[] enumNames = Enum.GetNames(typeof (SearchComparision));
var al = new ArrayList();
for (int i = 0; i < enumNames.Length; i++)
al.Add(new {Value = i, Name = enumNames[i]});
scOperatorSelection.DataValueField = "Value";
scOperatorSelection.DataTextField = "Name";
...
The data to be displayed is added to the user control as a Field, defined above Page_Load. The signature of the events is the following:
public delegate void ControlStateChanged(object sender, SearchCriteriaEventArgs eventArgs);
public event ControlStateChanged ItemUpdated;
public event ControlStateChanged ItemRemoved;
public event ControlStateChanged ItemAdded;
The update button on the user control triggers the following method:
protected void UpdateCriteria(object sender, EventArgs e)
{
var searchCritCtl = (SearchCriteria) sender;
var scEArgs = new SearchCriteriaEventArgs
{
TargetCriteria = searchCritCtl.CurrentCriteria.CriteriaId,
SearchComparision = ParseCurrentComparer(searchCritCtl.scOperatorSelection.SelectedValue),
SearchField = searchCritCtl.scFieldSelection.SelectedValue,
SearchValue = searchCritCtl.scFilterValue.Text,
ClickTarget = SearchCriteriaClickTarget.Update
};
if (ItemUpdated != null)
ItemUpdated(this, scEArgs);
}
The rendering page fetches the data objects from a storage backend and displays it in it's Page_Load event. This is the point where it starts getting tricky: i connect to the custom events!
int idIt = 0;
foreach (var item in _currentSearch.Items)
{
SearchCriteria sc = (SearchCriteria)LoadControl("~/content/controls/SearchCriteria.ascx");
sc.ID = "scDispCtl_" + idIt;
sc.ControlMode = SearchCriteriaMode.Display;
sc.CurrentCriteria = item;
sc.ItemUpdated += CriteriaUpdated;
sc.ItemRemoved += CriteriaRemoved;
pnlDisplayCrit.Controls.Add(sc);
idIt++;
}
When first rendering the page, everything is displayed fine, i get all my data. When i trigger an update event, the user control event is fired correctly, but all fields and controls of the user control are NULL. After a bit of research, i had to come to the conclusion that the event is fired before the controls are initialized...
Is there any way to prevent such behavior / to override the page lifecycle somehow? I cannot initialize the user controls in the page's Init-event, because i have to access the Session-Store (not initialized in Page_Init).
Any advice is welcome...
EDIT:
Since we hold all criteria informations in the storage backend (including the count of criteria) and that store uses the userid from the session, we cannot use Page_Init... just for clarification
EDIT #2:
I managed to get past some of the problems. Since i'm now using simple types, im able to bind all the data declaratively (using a repeater with a simple ItemTemplate). It is bound to the control, they are rendered in correct fashion. On Postback, all the data is rebound to the user control, data is available in the OnDataBinding and OnLoad events, everything looks fine.
But as soon it enters the real event (bound to the button control of the user control), all field values are lost somehow...
Does anybody know, how the page lifecycle continues to process the request after Databinding/Loading ? I'm going crazy about this issue...
Dynamic controls are can be a nightmare. The trick is to make sure you rebind everything on the postback.
I figured out a solution ;)
If i work with the OnCommand event on the buttons inside the usercontrol, i can pass a CommandArgument. Now im binding the collection identifier to the CommandArgument parameter of the button which enables me to handle all postbacks inside the usercontrol.
<asp:Button ID="scUpdate"
runat="server"
Text="Update"
OnCommand="HandleCommand"
CommandName="update"
CommandArgument='<%# CriteriaId %>' />
This declaration preserves the CriteriaId (a Guid) throughout postbacks and enables me to identify the modified entry on the underlying collection (managed on the page). The following code snippet shows how the event to the subscribing page is triggered.
scEArgs = new SearchCriteriaEventArgs
{
TargetCriteria = new Guid(e.CommandArgument.ToString()),
SearchComparision = ParseCurrentComparer(),
SearchField = scFieldSelection.SelectedValue,
SearchValue = scFilterValue.Text,
ClickTarget = SearchCriteriaClickTarget.Update
};
if (ItemUpdated != null)
ItemUpdated(this, scEArgs);
Maybe this answer helps somebody so i'll just post it ;)

Custom Validator with an OR Condition

Right now i have an asp.net 2.0 app which allows a user to search by the following fields
Location (Required if there is nothing in idnumber field)
Address (Required if there is nothing in idnumber field)
Zip (Required if there is nothing in idnumber field)
**OR**
IDNumber. (Required if there is nothing in any of the other fields)
What i'd like to be able to do is validate this client side on button click and display a summary of errors.
i.e.
if a user leaves every criteria blank. I'd like to display "You must enter a IDNumber or "Location, Address, and Zip to continue"
I've never used the Custom Validation control so here are some questions.
1) Is it able to do this?
2) Does anyone have an example of how to do this?
Thanks
You can use the ClientValidationFunction property of a CustomValidator control to specify a Javascript function that will validate your form. You'll need to write the JavaScript for the validation. Unless you're writing an application where you can be absolutely sure that all of your clients have JavaScript enabled, I highly recommend you also use the OnServerValidate property to also provide server-side validation.
Server-side CustomValidator example: https://web.archive.org/web/20211020145934/https://www.4guysfromrolla.com/articles/073102-1.aspx
Client-side example: http://www.codeproject.com/KB/custom-controls/CustomValidatorAndSummary.aspx
It is fairly simple to use a custom validator. Add one to your page, and choose the ServerValidate event, which will generate a function like this (example in C#):
protected void CustomValidator1_ServerValidate(object source,
ServerValidateEventArgs args)
{
// Your validation logic goes here... set args.IsValid = true if it passes,
// false otherwise. Here is an example...
args.IsValid = false;
if(txtIDNumber.Text.Length > 0)
{
args.IsValid = true;
}
else if (txtLocation.Text.Length > 0
&& txtAddress.Text.Length > 0
&& txtZip.Text.Length > 0)
{
args.IsValid = true;
}
}

Resources