Adding unique ValidationGroup names to forms - asp.net

I have a problem when adding modules/controls to a webpage in a ASP.NET CMS which have form validation that it would validate all forms on the page, because the ValidationGroup has the same name. How to solve this with a function?

I came up with below solution:
A function that iterates through a certain placeholder to assign unique ValidationGroup names to each form.
Public Shared Sub SetValGroupControls(PageModule As Control, valGroupName As String)
For Each ctrl As Control In PageModule.Controls
If TypeOf ctrl Is RequiredFieldValidator Then
DirectCast(ctrl, RequiredFieldValidator).ValidationGroup = valGroupName
ElseIf TypeOf ctrl Is RegularExpressionValidator Then
DirectCast(ctrl, RegularExpressionValidator).ValidationGroup = valGroupName
ElseIf TypeOf ctrl Is CompareValidator Then
DirectCast(ctrl, CompareValidator).ValidationGroup = valGroupName
ElseIf TypeOf ctrl Is CustomValidator Then
DirectCast(ctrl, CustomValidator).ValidationGroup = valGroupName
ElseIf TypeOf ctrl Is RangeValidator Then
DirectCast(ctrl, RangeValidator).ValidationGroup = valGroupName
ElseIf TypeOf ctrl Is Button Then
DirectCast(ctrl, Button).ValidationGroup = valGroupName
End If
If ctrl.Controls.Count > 0 Then
SetValGroupControls(ctrl, valGroupName)
End If
Next
End Sub
Where PageModule represents the placeholder where the validation controls are contained (to avoid iterating through all controls on the page) and the ValGroupName represents the unique string which will be assigned as name.
Assuming my validation controls are contained in a placeholder that is called 'plhMyForm' you can call the function like this:
Dim nGuid = String.format("{0}-validation", Guid.NewGuid())
SetValGroupControls(plhMyForm, nGuid)
Above will create a unique string like:
24ad5ae3-fead-4a6f-98f3-dffcd2e815ba-validation
Of course you can use your own unique string generation.
Now you can leave your ValidationGroup name empty and the function assigns one for you. This way every form on the same page that requires validation will individually validate itself.

Related

telerik grid edit with validators seems overlapped

i have a telerik grid for asp.net ajax with AllowAutomaticxxxx properties set to true and EditMode="EditForms".
The mastertableview is for Divisions and detail table is for functions. Currently am able to insert new division and function and also edit division and function. i am using required field validator for both divisions and functions. now am facing a problem. the validator appears as overlapped when opening one edit function and one insert division.i mean when they are opened at the same time, and when i edited the function and clicked the update button, the validator for division name appears!!
1 more thing i have used ajaxmanager for the grid and i am not sure whether this is the issue.
i solved this issue by setting validationgroup for each edit and delete like this in the itemCreated event of the grid
If TypeOf e.Item Is Telerik.Web.UI.GridEditableItem AndAlso e.Item.IsInEditMode Then
If "Divisions".Equals(e.Item.OwnerTableView.Name) Then
Dim rvDivisionName = DirectCast(e.Item.FindControl("rvDivisionName"), RequiredFieldValidator)
If TypeOf e.Item Is Telerik.Web.UI.GridEditFormInsertItem Then
rvDivisionName.ValidationGroup = "addDivisionRowValidation"
TryCast(TryCast(e.Item, Telerik.Web.UI.GridEditFormItem).FindControl("PerformInsertButton"), LinkButton).ValidationGroup = "addDivisionRowValidation"
Else
rvDivisionName.ValidationGroup = "editDivisionRowValidation"
TryCast(TryCast(e.Item, Telerik.Web.UI.GridEditFormItem).FindControl("UpdateButton"), LinkButton).ValidationGroup = "editDivisionRowValidation"
End If
ElseIf "Functions".Equals(e.Item.OwnerTableView.Name) Then
Dim rvFunctionName = DirectCast(e.Item.FindControl("rvFunctionName"), RequiredFieldValidator)
Dim rvFunctionRoleName = DirectCast(e.Item.FindControl("rvFunctionRoleName"), RequiredFieldValidator)
If TypeOf e.Item Is Telerik.Web.UI.GridEditFormInsertItem Then
rvFunctionName.ValidationGroup = "addFunctionRowValidation"
rvFunctionRoleName.ValidationGroup = "addFunctionRowValidation"
TryCast(TryCast(e.Item, Telerik.Web.UI.GridEditFormItem).FindControl("PerformInsertButton"), LinkButton).ValidationGroup = "addFunctionRowValidation"
Else
rvFunctionName.ValidationGroup = "editFunctionRowValidation"
rvFunctionRoleName.ValidationGroup = "editFunctionRowValidation"
TryCast(TryCast(e.Item, Telerik.Web.UI.GridEditFormItem).FindControl("UpdateButton"), LinkButton).ValidationGroup = "editFunctionRowValidation"
End If
End If
End If

Accessing server-side control by its ID property in ASP.net

On my default.aspx page I have a bunch of divs with an ID and runat="server":
<div id="serverOne" runat="server"></div>
<div id="serverTwo" runat="server"></div>
<!--etc...-->
In my code behind I've declared a multidimensional array (or grid) with 2 values -- the first being an IP address and the second the server name.
Dim servers = {{"10.0.0.0", "serverOne"}, {"10.0.0.1", "serverTwo"}}
My question is, is there a way where I can target my divs from my code behind using a value from the array?
For i As Integer = 0 To 1
'This is what I want it to do:
servers(i, 1).InnerHtml = "<span>Testing " & servers(i, 1) & "</span>"
Next
You can do this using the FindControl method on the page. However, out of the box FindControl looks only at the first level of children, and does not go into the childrens' children. In order to handle this you need to use a helper method that allows FindControl to recursively search through the control hierarchy to find the one you want. Add this method to your code behind, or some shared class that multiple pages can access:
Protected Function FindControlRecursive(control As Control, id As String)
If (control.ID = id) Then
Return control
End If
For Each ctl In control.Controls
Dim foundControl = FindControlRecursive(ctl, id)
If (foundControl IsNot Nothing) Then
Return foundControl
End If
Next
Return Nothing
End Function
Once you have that, it's pretty easy to find your <div> just by using the string ID property.
For i As Integer = 0 To 1
Dim div = CType(FindControlRecursive(Me, servers(i, 1)), HtmlGenericControl)
div.InnerHtml = "<span>Testing " & servers(i, 1) & "</span>"
Next
Reference: http://forums.asp.net/t/1107107.aspx/1

User Control validation group issue

I have two instances of a user control on a page. Both have fields and one submit button.
I have set validation groups on the fields and validators but for some reason when validating the two user controls' validators fire.
This method also works:
Dim valGroup = String.format("{0}-validation", Guid.NewGuid())
rfv001.ValidationGroup = valGroup
rfv002.ValidationGroup = valGroup
rfv003.ValidationGroup = valGroup
rfv004.ValidationGroup = valGroup
rfv005.ValidationGroup = valGroup
btnSubmit.ValidationGroup = valGroup
You only need to set the values for the ValidationGroup manually.
You could expose a property ValidationGroup in your UserControl that you would set from the Page. This value should be stored in ViewState, so that every instance of the UserControl will get different ValidationGroups(if your page assigns different).
For example:
Public Property ValidationGroup() As String
Get
Return CStr(ViewState("ValidationGroup"))
End Get
Set(ByVal value As String)
SetValidationGroupOnChildren(Me, value)
ViewState("ValidationGroup") = value
End Set
End Property
Private Sub SetValidationGroupOnChildren(ByVal parent As Control, ByVal validationGroup As String)
For Each ctrl As Control In parent.Controls
If TypeOf ctrl Is BaseValidator Then
CType(ctrl, BaseValidator).ValidationGroup = validationGroup
ElseIf TypeOf ctrl Is IButtonControl Then
CType(ctrl, IButtonControl).ValidationGroup = validationGroup
ElseIf ctrl.HasControls() And ctrl.Visible = True Then
SetValidationGroupOnChildren(ctrl, validationGroup)
End If
Next
End Sub
http://www.craigwardman.com/blog/index.php/2009/05/setting-a-validation-group-on-a-user-control/
http://justgeeks.blogspot.com/2009/09/be-careful-using-hard-coded.html
If you need different ValidationGroups in your UserControl the above recursive function won't work, then you could assign it manually from codebehind. For example by putting the UserControl's ID(might suffice) or ClientID in front of the ValidationGroup properties of the according controls. A good place where you could call this function would be PreRender.

Custom Validator Not Firing (No error message, but no validation)

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

Getting information (on click) that was used to programatically generate asp controls

How may one get information that was used to programatically generate asp controls?
For example, I pulled a DataTable of user objects from the database and have organized them on a page, listing groupings such as a list of employees directly under the employer for each employer. On the page, I list each user's Username as a LinkButton. When I click one of these employees, I want to redirect the page (which is easy) and set a session variable to the selected user's UserId (which seems not so easy). How can I pull this UserId value back? These elements are not hard-coded with nice names (as they are generated in a for each loop).
Code from comment below:
Dim lnkbtnPm As New LinkButton ' is my link button. '
lnkbtnPm.Text = pmDr.Item("Username") ' where pmDr is my datarow. '
lnkbtnPm.CommandArgument = pmDr.Item("UserId")
lnkbtnPm.CommandName = "CommandNameHere"
panelToAddControlTo.Controls.Add(lnkbtnPm)
Thanks :)
I think this is what you would use the CommandName and CommandArgument properties of the LinkButton for. Assign the user id as CommandArgument and a suitable string as CommandName and hook up the Command event to an event handler:
Sub LinkButton_Command(sender As Object, e As CommandEventArgs)
' e.CommandArgument will contain the user id '
End Sub
Update
The problem is that the event handler is never attached. Use AddHandler to do that:
Dim lnkbtnPm As New LinkButton
lnkbtnPm.Text = pmDr.Item("Username") ' where pmDr is my datarow. '
lnkbtnPm.CommandArgument = pmDr.Item("UserId")
lnkbtnPm.CommandName = "CommandNameHere"
AddHandler lnkbtnPm.Command, AddressOf LinkButton_Command
panelToAddControlTo.Controls.Add(lnkbtnPm)

Resources