Custom Validator Not Firing (No error message, but no validation) - asp.net

I have a custom validator:
<asp:CustomValidator ID="QuestionValidator" runat="server" ErrorMessage="Please select an option" ClientValidationFunction="QuestionValidator_ServerValidate" OnServerValidate="QuestionValidator_ServerValidate" ValidateEmptyText="true"></asp:CustomValidator>
I have a list of questions provided by a datalist, which I need to ensure a user selects an answer to each question. I then have my validation functions:
Protected Sub QuestionValidator_ServerValidate(ByVal source As Object, ByVal args As ServerValidateEventArgs)
Dim SelectedItem As Boolean = False
For Each c As Control In Page.Master.FindControl("form1").Controls
If TypeOf c Is RadioButton Then
Dim rb As RadioButton = DirectCast(c, RadioButton)
If rb.GroupName = "AnswerOptions" AndAlso rb.Checked = True Then
SelectedItem = True
End If
End If
Next
args.IsValid = SelectedItem
End Sub
<script type="text/javascript" language="javascript">
function QuestionValidator_ServerValidate() {
return true;
}
</script>
When I run the page, there is no validation and no error message. Please can you point out where I am going wrong, I'm suspicious it is at Page.Master.FindControl("form1").Controls.
I have previously done such validation by looping through controls via form1.controls but this is unavailable as the page uses a form passed down via the master page.

There could be a flaw in your code. Because as per the logic if out of 50 radio buttons on your page even if just one is selected your validation will pass. Also the groupname for all the RBs is same for each item. Not sure if ASP.NET renames those and if not then all RBs with be grouped into one for all the questions.
For the looping part you can loop through DataList.Items collection instead of looping through all controls on the form:
Dim item As DataListItem
For Each item In DataList1.Items
Dim ctrl As Control
For Each ctrl In item.Controls
'do your rb state check here
Next ctrl
Next item

I would try looping through either "Page.NamingContainer" or "Page.Controls" and see how that goes.

Maybe I missed something, but shouldn't You also set property ControlToValidate="ID_of_the_control_to_validate" in the custom validator?

I think you need to give ValidationGroup for the CustomValidator and all the Controls Involved in the Validaiton process

Related

color styling tablecell based upon value

I am trying to style tablecells based upon the text value of the cell. This is being done on specific fields to draw user attention These tablecells are hosted inside of a formview with an itemTemplate of asp:table object. The cells have an ID and are set to run at the server side so that I can grab them from codebehind.
I attempted to hook into the individual cells by handling the onDatabound, onPrerender, onLoad events of the tablecell. onPreRender is used in my code snippet but results were same on all three tablecell events. In handling these events I always had a string.empty for the text property instead of the actual value (even after databind was called). Because I didn't have the actual value my comparisons did not pass and my color styling did not get set as desired.
edit: I also tried handling the databound event of my formview to get to my cell values. No luck there either.
Here's relevant markup:
<asp:FormView ID="fvShipments" runat="server" DefaultMode="readonly">
<ItemTemplate>
<asp:Table ID="tblShipments" runat="server" GridLines="Both">
<asp:TableRow runat="server">
<asp:TableCell runat="server" ID="tbcCartonSizeOverride" CssClass="table-displayrow centerText" OnPreRender="tbcCartonSizeOverride_PreRender"><%#Eval("CartonSizeOverRide")%></asp:TableCell>
Here's relevant codebehind
Protected Sub tbcCartonSizeOverride_PreRender(sender As Object, e As EventArgs)
markAflag(CType(sender, TableCell))
End Sub
Private Sub markAflag(ByRef cell As TableCell)
If cell.Text.Trim.Length > 0 Then
cell.BackColor = Drawing.Color.Orange
Else
cell.BackColor = Drawing.Color.White
End If
End Sub
I'm not understanding why this isn't working. Unless my Eval markup solves AFTER prerender event?
Thanks for reading. I don't work with asp often so it's possible I have something simple confused here.
Ok I solved this issue by setting some datakeys on my formview object and doing a findcontrol call at runtime to get a reference to my table on the page. Here's some sample code that demonstrates what I did.
Private Sub colorReturncode()
Dim schedreturncode As Integer
schedreturncode = FormView1.DataKey(1)
Dim qtable As New Table
qtable = CType(FormView1.FindControl("table1"), Table)
If schedreturncode = 0 Then
qtable.Rows(4).Cells(2).BackColor = System.Drawing.Color.Green
qtable.Rows(4).Cells(2).ForeColor = System.Drawing.Color.White
ElseIf schedreturncode = -1 Then
qtable.Rows(4).Cells(2).BackColor = System.Drawing.Color.White
Else
qtable.Rows(4).Cells(2).BackColor = System.Drawing.Color.Red
qtable.Rows(4).Cells(2).ForeColor = System.Drawing.Color.White
End If
End Sub

How to apply Client-side validation by calling a server-side function in ASP.NET

I have an ASP.NET Web Forms application.
I have a Form with various TextBoxand right now I have several asp:RequiredFieldValidator linked to them belonging to the same ValidationGroup.
Now I have to apply to some TextBox an additional validation with related error message.
In the specific I got to check whether the text inside the TextBox is a Guid or not. Morevoer this check has to be done on the fly, meaning that as soon as the user moves the cursor from the TextBox the validation has to be performed, without the need to press submit.
How can I call the IsGuid(string guid) function from Javascript?
How can I attach two different error messages as validation (for instance I want to be displayed a message if TextBox.Text has carachters not allowed and lenght < N)
Is it easier to implement this validation with jQuery or with the ASP.NET validators?
If somebody else has any other idea for its implementation, please feel free to propose. Thanks!
You can use ReqularExpressionValidator control.
Here a regex
^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$
You can apply as many Validators as you need to the same control, in this case your TextBox.
In this scenario, a Custom Validator is the way to go because it enables you to do the validation with any function you develop to cover your needs. Please, have a look at this simple tutorial.
UPDATE 1: Server Side Validation
This is how it calls the server side function in the declaration of the CustomValidator:
<asp:CustomValidator runat="server" id="custPrimeCheck"
ControlToValidate="txtPrimeNumber"
OnServerValidate="PrimeNumberCheck"
ErrorMessage="Invalid Prime Number" />
Example of the "PrimeNumberCheck" VB function:
Sub PrimeNumberCheck(sender as Object, args as ServerValidateEventArgs)
Dim iPrime as Integer = Cint(args.Value), iLoop as Integer, _
iSqrt as Integer = CInt(Math.Sqrt(iPrime))
For iLoop = 2 to iSqrt
If iPrime mod iLoop = 0 then
args.IsValid = False
Exit Sub
End If
Next
args.IsValid = True
End Sub
UPDATE 2: Client Side Validation
This is how it calls the server side function in the declaration of the CustomValidator:
<asp:CustomValidator runat="server" id="custPrimeCheck"
ControlToValidate="txtPrimeNumber"
ClientValidationFunction="CheckPrime"
ErrorMessage="Invalid Prime Number" />
Example of the "CheckPrime" JavaScript function:
function CheckPrime(sender, args)
{
var iPrime = parseInt(args.Value);
var iSqrt = parseInt(Math.sqrt(iPrime));
for (var iLoop=2; iLoop<=iSqrt; iLoop++)
if (iPrime % iLoop == 0)
{
args.IsValid = false;
return;
}
args.IsValid = true;
}
Thanks to #AdrianIftode for making me aware of this.

CustomValidator not working

I have a CustomValidator that checks if text entered in textboxes matches certain fields in a database. This was all working great before, but I have modified my page quite a bit since then and it is no longer working. I didn't think I changed anything that would affect this, but apparently I did. All my other validators (required field validators) are working correctly, but my CustomValidator isn't responding.
So anyway, here is my code:
CustomValidator:
<asp:CustomValidator ID="CustomValidator1" runat="server" ControlToValidate="txtCoursePrefix" ErrorMessage="Course number is already taken."></asp:CustomValidator>
VB codebehind:
Protected Sub CustomValidator1_ServerValidate(ByVal source As Object, ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) Handles CustomValidator1.ServerValidate
'Checking for duplicate course numbers
'get values
Dim checkPrefix = txtCoursePrefix.Text
Dim checkNum = txtCourseNum.Text
'db connectivity
Dim myConn As New OleDbConnection
myConn.ConnectionString = AccessDataSource2.ConnectionString
myConn.Open()
'select records
Dim mySelect As New OleDbCommand("SELECT 1 FROM tableCourse WHERE prefix=? AND course_number=?", myConn)
mySelect.Parameters.AddWithValue("#checkPrefix", checkPrefix)
mySelect.Parameters.AddWithValue("#checkNum", checkNum)
'execute(Command)
Dim myValue = mySelect.ExecuteScalar()
'check if record exists
If myValue IsNot Nothing Then
CustomValidator1.SetFocusOnError = True
args.IsValid = False
End If
End Sub
Everything is working up until CustomValidator1.SetFocusOnError = True and args.IsValid = False. I have tested the If statement and it's working correctly, it returns true and anything else I put inside of it executes.
Things you should know when using customvalidators:
If you are validating using a ValidationGroup, don't forget to add it to your CustomValidator.
Set the ControlToValidate property.
A CustomValidator control never fires when the ControlToValidate control is empty unless you set ValidateEmptyText=true.
When using ClientValidationFunction="customClientValidationFunction" use the following signature:
function customClientValidationFunction(sender, arguments) {
arguments.IsValid = true; //validation goes here
}
You should set the property ValidateEmptyText="true" on the CustomValidator. The client and server functions will always be called in that case.
It solved the problem for me.
If the handler is getting called, and you're successfully setting the args.IsValid to false, then what that does is it sets Page.IsValid to false. But unfortunately, that doesn't stop the form from being sumbitted. What you need to do is check that Page.IsValid property in your code that handles your form submit, like in the submit button handler.
So in addition to the code you posted, which sounds like it is working correctly, make sure that you have something like this for your submit handler (C# example):
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (!Page.IsValid)
{
// by simply returning, the error message for the CustomValidator will be displayed
return;
}
// do processing for valid form here
}
Use this
OnServerValidate="CustomValidator1_ServerValidate"
like an example and it will work....
<asp:CustomValidator ID="CustomValidator1" runat="server" ControlToValidate="txtCoursePrefix" ErrorMessage="Course number is already taken." OnServerValidate="CustomValidator1_ServerValidate"></asp:CustomValidator>
Gaurav Agrawal
First of all, put validation group on validators and the button. If that too doesnt work, put OnClientClick='CheckValidate();' and declare the function which will call page_clientvalidate method along with the parameter.. validation group. This would surely work. If that is not working put debugger in the javascript method and debug the same

ASP.NET Dynamic User Controls

I'm sure this question has been asked a million times, however I haven't been able to find an answer that solves my problem.
I am programmatically adding some custom user controls to a PlaceHolder which I have on a simple aspx page. All of the user controls Postback's work correctly except for one which has a Gridview on it.
For some reason any postback that gets fired from within this control, does not call the specified event on the first click, however all future clicks it will work fine. I have no idea why this is the case, but many solutions I have found, suggest adding an ID to the ascx User Control, however this doesn't work in my case.
I've taken a look at the source file for the page that gets generated before and after the first click, javascript used for calling the postback changes, i.e
Before first click: onclick="javascript:__doPostBack('tmpControlID$sgvPrimaryEmploymentHistory','Select$0')"
After first click: onclick="javascript:__doPostBack('OFFHome1$tmpControlID$sgvPrimaryEmploymentHistory','Select$0')"
OFFHome1 is the parent user control which exists on the aspx page. All other controls are added to a placeholder in this control, i.e.
<%# Control Language="vb" AutoEventWireup="false" CodeBehind="OFFHome.ascx.vb" Inherits="UmbracoUserControls.OFFHome" %>
<asp:PlaceHolder ID="phOFFSection" runat="server"></asp:PlaceHolder>
Nothing to complicated. Then in the code behind the controls are loaded into the placeholder using the following:
Private Sub LoadNextOFFStep()
Dim ControlName As String = "TestControl.ascx"
phOFFSection.Controls.Clear()
If ControlName IsNot Nothing AndAlso ControlName <> String.Empty Then
Dim NewControl As Object = LoadControl(ControlName)
With NewControl
.ID = USERCONTROLNAME
Dim StepCompleted As Boolean = .FillControl()
If StepCompleted Then
Exit Sub
End If
Dim AllowSkip As Boolean = .AllowSkip()
btnSkip.Visible = AllowSkip
End With
phOFFSection.Controls.Add(NewControl)
End If
End Sub
Again, nothing overly complicated. The USERCONTROLNAME is just a const with the value "tmpControlID" in it.
The control that is giving me trouble is a little complicated, I was originally using a custom GridView control that we have created, but have removed it and replaced it with the standard asp one to see if the problem still occurs, and it does.
Any button, on control which fires off a postback will fail the first time, and all future click will work correctly. On the first click the Page_Load event will get called, but that is it.
What am I doing wrong??
After far too much time spent on this, I have finally worked it out.
It was to do with the order of events, however just not where I had thought. The FillControl function was getting called before User Control had been added to the PlaceHolder. I changed this so that it gets called after the User Control was added to the PlaceHolder and now it works first time.
Basically the code looks like this now:
Private Sub LoadNextOFFStep()
Dim ControlName As String = "TestControl.ascx"
phOFFSection.Controls.Clear()
If ControlName IsNot Nothing AndAlso ControlName <> String.Empty Then
Dim NewControl As Object = LoadControl(ControlName)
With NewControl
.ID = USERCONTROLNAME
Dim AllowSkip As Boolean = .AllowSkip()
btnSkip.Visible = AllowSkip
End With
phOFFSection.Controls.Add(NewControl)
Dim StepCompleted As Boolean = CType(phOFFSection.Controls(0), Object).FillControl()
If StepCompleted Then
LoadNextOFFStep()
Exit Sub
End If
End If
End Sub
Thanks for everyone's help.
Well... the answer to the first question is simple: It fails the first time because the ID of the control (or rather, in the postback script) is different on subsequent page loads. It works on subsequent clicks because the control ID stays the same.
Now as to WHY that is... much tougher! But probably something to do with the order of operations here.
Try explicitly setting the NamingContainer value for NewControl:
With NewControl
.NamingContainer = OffHomeOne; // whatever
.ID = USERCONTROLNAME

DropDownList SelectedIndex value not updating on AutoPostback

It looks like this question was addressed here, but his solution did not work for me. I am creating a dynamic dropdown menu system that populates a secondary dropdownlist with the results of a query based on the selected item in the first dropdown.
First dropdown getting populated:
Dim db As New linqclassesDataContext
Dim categories = (From c In db.faq_cats)
NewFaqDropDownCategory.DataSource = categories
NewFaqDropDownCategory.DataTextField = "category"
NewFaqDropDownCategory.DataValueField = "category_id"
NewFaqDropDownCategory.DataBind()
Unset(categories)
Unset(db)
Second dropdown getting populated:
Protected Sub NewFaqDropDownCategory_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Dim temp As Integer = CInt(Val(NewFaqDropDownCategory.SelectedIndex))
MsgBox(theDrop.SelectedValue)
Return
'Dim db As New linqclassesDataContext
'Dim faqs = (From f In db.faqs Where f.category = NewFaqDropDownCategory.SelectedValue)
'NewFaqDropDownList.DataSource = faqs
'NewFaqDropDownList.DataTextField = "question"
'NewFaqDropDownList.DataValueField = "id"
'NewFaqDropDownList.DataBind()
'NewFaqLabel.Visible = True
'NewFaqDropDownList.Visible = True
'Unset(faqs)
'Unset(db)
End Sub
The markup for the first dropdown...
<asp:DropDownList ID="NewFaqDropDownCategory" AutoPostBack="true" runat="server" OnSelectedIndexChanged="NewFaqDropDownCategory_SelectedIndexChanged">
</asp:DropDownList>
And the second...
<asp:DropDownList ID="NewFaqDropDownList" runat="server" Visible="false">
</asp:DropDownList>
No matter what I have tried, I always get "1" (the value of the first item in the second dropdown). The post I referenced earlier said this had to do with AutoPostBack and the server not knowing the list was updated yet.
Can anyone clarify this for me a little more?
Set a break point on the line that reads: NewFaqDropDownCategory.DataBind() and one in your event handler (NewFaqDropDownCategory_SelectedIndexChanged).
I suspect the databind is being called right before your NewFaqDropDownCategory_SelectedIndexChanged event fires causing your selected value to change.
If so, you need either to make sure you only databind if you aren't in the middle of your autopostback or instead of using NewFaqDropDownCategory.SelectedIndex on the first line of your event handler you can cast the sender parameter to a DropDownList and use its selected value.
I had the same problem. Found I forgot to look if I was posting back to the page or not and I was binding my DropDownList control in the Page_Load event of the page.
I had forgot to use:
if (!IsPostBack)
{
.... do databind ....
}
I think there is a bug in your LINQ query for the second drop down box
Dim faqs = (From f In db.faqs Where f.category = NewFaqDropDownCategory.SelectedValue)
Here you are comparing SelectedValue to category. Yet in the first combobox you said that the DataValueField should be category_id. Try changing f.category to f.category_id

Resources