Custom validator dynamic ServerValidate using Reflection - asp.net

I have a UserControl which contains a TextBox and a CustomValidator.
I would like to set the CustomValidator.ServerValidate to a method in the page that contains the UserControl
I found this code which will allow me to dynamically set the custom validators validation function:
cusvCustom.ServerValidate += new System.Web.UI.WebControls.ServerValidateEventHandler(MethodName);
The problem is that a string value won't work there. It needs to be a reference to the method. Is it possible to use reflection (or some other method) to get a valid reference to the parent controls method using only the string name of it? The reason I want to use the string value of the method name is so I can place the control on the page thusly:
<uc1:TextBoxField ID="tbUserName" runat="server" CustomValidationMethod="ValidateUserName" />
I did some research and I found Type.GetMethod and MethodInfo but I can't get them to work. Primarily because I don't know the type of the parent control and can't figure out how to get it.
EDIT: My code for matt-dot-net
WebUserControl.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl.ascx.cs" Inherits="WebApplication1.WebUserControl" %>
<asp:CustomValidator ID="CustomValidator1" runat="server" ErrorMessage="Custom Validation Failed" OnServerValidate="CustomValidator1_ServerValidate" />
<asp:TextBox ID="TextBox1" runat="server" />
<asp:Button ID="Button1" runat="server" Text="Submit" CausesValidation="true" />
WebUsecControl.ascx.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class WebUserControl : System.Web.UI.UserControl
{
public ServerValidateEventHandler Validating;
protected void CustomValidator1_ServerValidate(object sender, ServerValidateEventArgs e)
{
if (Validating != null)
Validating(sender, e);
}
}
}
TestPage.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="TestPage.aspx.cs" Inherits="WebApplication1.TestPage" %>
<%# Register Src="~/WebUserControl.ascx" TagName="WebUserControl" TagPrefix="uc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<uc1:WebUserControl ID="WebUserControl1" runat="server" OnValidating="WebUserControl1_Validating" />
</div>
</form>
</body>
</html>
TestPage.aspx.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class TestPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//WebUserControl1.Validating += WebUserControl1_Validating;
}
protected void WebUserControl1_Validating(Object sender, ServerValidateEventArgs e)
{
e.IsValid = false;
}
}
}
As you can see it's almost an exact duplicate of your code. For whatever reason it does not work for me as I have it here. When I click on the button the page reloads and is the same. When I un-comment the one line though and click the button then I see the error message.

I think this is what you want to do:
WebUserControl.ascx:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="WebUserControl.ascx.cs" Inherits="WebUserControl" %>
<asp:CustomValidator ID="CustomValidator1" runat="server" ErrorMessage="Custom Validation Failed"
ControlToValidate="TextBox1" OnServerValidate="CustomValidator1_ServerValidate" />
<asp:TextBox ID="TextBox1" runat="server" />
<asp:Button ID="Button1" runat="server" Text="Submit" CausesValidation="true" />
And in your code behind:
public partial class WebUserControl : System.Web.UI.UserControl
{
public event ServerValidateEventHandler Validating;
protected void CustomValidator1_ServerValidate(object sender, ServerValidateEventArgs e)
{
if (Validating != null)
Validating(sender, e);
}
}
This will allow you to use the control on a page the way you want to:
<uc1:WebUserControl ID="WebUserControl1" runat="server" OnValidating="WebUserControl1_Validating" />
Then in your .aspx.cs code behind:
protected void WebUserControl1_Validating(Object sender, ServerValidateEventArgs e)
{
//do validation here
}

Related

ASP Data-binded dropdown list without autopostback

I have a simple form with a dropdown list binded to a string array (as a simple example). The form is submitted when the user clicks a button.
I want to query the selected item in the list. I read the SelectedValue member of the dropdownlist which always contains the default item no matter what I select in the form.
I can't use autopostback on the list as in my production environment the form is displayed in dynamic div using jquery.
If I remove the binding and add the list items in the asp file using ListItems tags, than it magically works.
My sample asp code:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:DropDownList ID="DropDownList1" runat="server">
</asp:DropDownList>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
</div>
</form>
</body>
</html>
And the code-behind file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string[] items = { "bindItem1", "bindItem2", "bindItem3" };
DropDownList1.DataSource = items;
DropDownList1.DataBind();
}
protected void Button1_Click(object sender, EventArgs e)
{
string text = TextBox1.Text;
string item = DropDownList1.SelectedValue;
}
}
In the page_load do the databinding only if Page.IsPostBack==False.
if (!IsPostBack)
{
//do the data binding
}
Your code now on every page load, will bind the data again and again, so the selected value is "not" changing.

how to change the inner html of a div

i have a div and an html editor and trying to:
add the div inner html to the
editor. (thats done)
then any changes done in the editor
is saved back in the div.
here is the backcode :
protected void Page_Load(object sender, EventArgs e)
{
Editor.Content = cvDiv.InnerHtml;
}
protected void preview(object sender, EventArgs e) //this is an onclick event
{
cvDiv.InnerHtml = Editor.Content;
}
and the code for the editor:
<asp:ScriptManager runat="server" />
<cc1:Editor ID="Editor" runat="server" OnContentChanged="preview" />
<asp:Button runat="server" ID="eButton" CssClass="eButton" Text="Edit" OnClick="Edit" />// this is the button that is supposed to save
but it doesnt work.
so what i am trying to do is save whatever changes made in the editor to the div
using asp.net 3.5, and the ajax toolkit editor.
thanks in advance.
This is an example i've made to show you a working code.
ASPX
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true"></asp:ScriptManager>
<asp:TextBox id="editor" runat="server" AutoPostBack="true"></asp:TextBox>
<asp:Button ID="Save" runat="server" OnClick="SaveChange" Text="Save" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" >
<ContentTemplate>
<div id="preview" runat="server"></div>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="editor" EventName="TextChanged" />
</Triggers>
</asp:UpdatePanel>
</form>
</body>
</html>
ASPX.CS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack) editor.Text = preview.InnerHtml;
else preview.InnerHtml = editor.Text;
}
protected void SaveChange(object sender, EventArgs e)
{
string thingsToSave = preview.InnerHtml;
//Save to db/file/xml
}
}
Can you try using Literal control rather than a server side <div /> ?

UpdatePanel dynamically loaded Web UserControl will disappear after clicking any button inside the UserControl

I've a ASP.Net page (Default.aspx) which will load UserControl (ucontrol.ascx) dynamically into an UpdatePanel. By using UpdatePanel, we believe we're able to prevent the entire page to be posted-back.
My problem is, within the UserControl, we have some form controls, such as inputs and buttons; after the UserControl is loaded, clicking on any button inside the UserControl will cause the UpdatePanel to be blanked. During the investigation, I found that, breakpoints within the Button1_Click() in the code-behind for the UserControl is never reached. Please reference to the code below, this references to [REFERENCE]1. It's an urgent task, please kindly help.
Thanks!
William
Default.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<span>This is hosting page</span><br />
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Add UserControl" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1" />
</Triggers>
</asp:UpdatePanel>
<asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:PlaceHolder ID="PartHolder" runat="server">
</asp:PlaceHolder>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1" />
</Triggers>
</asp:UpdatePanel>
</form>
</body>
</html>
Default.aspx.cs:
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
loadparts();
}
private void loadparts(){
Control formpart = LoadControl("ucontrol.ascx");
formpart.ID = "formpart";
PartHolder.Controls.Add(formpart);
}
}
ucontrol.ascx:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="ucontrol.ascx.cs" Inherits="ucontrol" %>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
This is Web User Control in UpdatePanel<br />
<br />
<br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click"/>
ucontrol.ascx.cs:
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
public partial class ucontrol : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = TextBox1.Text;
TextBox1.Text = "";
TextBox1.Focus();
}
}
Here's what's happening:
First page load. No user control on page.
Person clicks Button1 on the page.
Page posts back (update panels do a full postback behind the scenes) and your Button1_Click handler on the page is run, which loads the user control into the page.
User now sees the user control and clicks ITS Button1.
Page posts back, but this time the Button1_Click handler on the page is not run (different button was clicked, even though you named them the same). Which means that loadparts() is not called and the user control is NOT loaded into the control tree.
Your Button1_Click handler in the user control is not run because the user control is not around to see that the button was clicked.
What you need to do is ensure that the user control is loaded into the page's control tree, even when you click the user control's button. That's why Andrew suggested you put the loadparts() into the Page_Load event. I can see that doesn't fit with the flow of your page, so you'll have to find another way to load it at the correct times.
try putting loadparts() method inside
protected void Page_Load(object sender, EventArgs e)
{
if(!isPostBack)
{
loadparts();
}
}
This worked for me:
protected void Page_Load(object sender, EventArgs e)
{
if(isPostBack)
{
loadparts();
}
}

Required field validator for multiple dropdown lists in an aspx page

I have an aspx page which has 18 (yes 18) dropdown lists and 18 text boxes. Each dropdown needs to be selected and each textbox needs to be filled. Dragging and dropping required field validators on these 36 controls and maintaining them is a painful task and does not seem to be the logical option as all I need is for the user to select a value from the dropdown.
Is there anyway I can loop through all these dropdown controls and textbox controls, check if they are empty and display warnings to users accordingly? Client-side validation solution or server side validation solution is fine with me.
Use a CustomValidator and have a client script function that makes sure every text box/drop down has a value.
One suggestion is to loop through all the controls on the page, use recursive function to dynamically bind RequiredFieldValidator to the found controls. You can tweak my code to suit your needs.
This code has some drawbacks though:
Use control.ID instead of associated label text
Adding RequiredFieldValidator to the page.controls will modify its ControlCollection. This will break the foreach method. Thus, I can only add RequiredFieldValidator to Panel instead.
.aspx
<asp:Panel ID="pnlValidation" runat="server">
</asp:Panel>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:TextBox ID="TextBox3" runat="server"></asp:TextBox>
<br />
<asp:DropDownList ID="DropDownList1" runat="server" />
<asp:DropDownList ID="DropDownList2" runat="server" />
<asp:DropDownList ID="DropDownList3" runat="server" />
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
.cs
protected void Page_Load(object sender, EventArgs e)
{
AddValidator(this);
}
private void AddValidator(Control ctrl)
{
if (ctrl is TextBox || ctrl is DropDownList)
{
RequiredFieldValidator rfv = new RequiredFieldValidator();
rfv.ControlToValidate = ctrl.ID;
rfv.Display = ValidatorDisplay.Dynamic;
rfv.ErrorMessage = ctrl.ID + " is required<br />";
pnlValidation.Controls.Add(rfv);
}
foreach (Control subctrl in ctrl.Controls)
AddValidator(subctrl);
}
If you are dynamically generating the textboxes and dropdownlists, you would probably want to dynamically generate the validation controls as well, but if all the drop down lists and textboxes are static you can use the following:
Use a CustomValidator Web Control, write client side javascript method that checks all the properties of the drop down lists and the textboxes and configure the web control's ClientValidationFunction with the function and set EnableClientScript=true. Also, b/c not all users have javascript enabled, plus to be sure as it is best practice, always also create a server side validation function as well and call Page.IsValid() on the submit action.
.aspx Sample Code
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs"
Inherits="Default2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script language="javascript" type="text/javascript">
function ValidateMe(sender, args) {
var txt = document.getElementById("txt");
if (txt.value != "")
args.IsValid = true;
else
args.IsValid = false;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:TextBox id="txt" runat="server" />
<asp:CustomValidator ClientValidationFunction="ValidateMe" ID="custval"
runat="server" ErrorMessage="Fail" onservervalidate="custval_ServerValidate" />
<asp:Button ID="btn" runat="server" Text="push" onclick="btn_Click1" />
</form>
</body>
</html>
c# codebehind sample code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Globalization;
using System.Threading;
public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
}
}
protected void btn_Click1(object sender, EventArgs e)
{
if (Page.IsValid)
{
btn.Text = "PASS";
}
else
{
btn.Text = "FAIL";
}
}
protected void custval_ServerValidate(object source, ServerValidateEventArgs args)
{
if (txt.Text != "")
custval.IsValid = true;
else
custval.IsValid = false;
}
}

How to use validator in this case is ASP.NET?

I have two input text boxes which are decimal.
The sum of the two inputs cannot be more than 100. When input1 is 40, input2 cannot be more than 60.
I need to do everything in client side and need to allow client to enter any value. If the entered value is more than the limit, I need to show the validator error message:
Page.isValid = false
Now I have two separate validator for each input box but I don't know how to change the valueToCompare of two validators in client side.
Please advise,
Thanks
You should look into using the CustomValidator control. Here's an article that walks you through using it.
Your code could look something like this:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
Inherits="WebApplication1._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript">
function validateTextBoxen(sender, args) {
// You'll have more thorough validation, I'm sure
var value1 = parseFloat(
document.getElementById('<%=textBox1.ClientID%>').value);
var value2 = parseFloat(
document.getElementById('<%=textBox2.ClientID%>').value);
args.IsValid = (value1 + value2) < 100;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="textBox1" runat="server" />
<asp:TextBox ID="textBox2" runat="server" />
<asp:CustomValidator runat="server" EnableClientScript="true"
OnServerValidate="onCustomValidation" ID="customValidator"
ErrorMessage="Invalid!"
SetFocusOnError="true" ClientValidationFunction="validateTextBoxen"/>
<asp:Button runat="server" OnClick="button_Click"/>
<asp:Literal runat="server" ID="placeholder" />
</div>
</form>
</body>
</html>
Code-behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class _Default : System.Web.UI.Page
{
protected void onCustomValidation(
object sender, ServerValidateEventArgs e)
{
float value1 = 0f;
float value2 = 0f;
if (!float.TryParse(textBox1.Text, out value1)
|| !float.TryParse(textBox2.Text, out value2)
|| value1 + value2 > 100f)
{
e.IsValid = false;
}
}
protected void button_Click(object sender, EventArgs args)
{
placeholder.Text = Page.IsValid ? "Valid" : "Invalid";
}
}
}
Nowadays the best way to validate HTML forms IMO is with a jQuery plugin like this one.
On client side, on the click of button, use ClientClick property, and set it to javascript function name to validate the input
e.g.
<asp:Button ID="btnSubmit" OnClientClick=" return validate()" runat="server" Text="Submit" ></asp:Button>
And write a validate() function in javascript, which check the sum of both inputs

Resources