Web User Controls and Validation - asp.net

I have an ASP.Net web user control that contains a TextBox and a calendar from the Ajax Control Toolkit.
When I include this user control on my page I would like it to participate in input validation (there is a required filed validator set on the TextBox inside the UC), ie. when the page is validated the content of the UC should also be validated. So I had my UC implement the IValidator interface, which worked well except that I could not set the validation group on the user control. Apparently I'm supposed to inherit from BaseValidator to do that, but I can't since I'm already inheriting UserControl.
There's got to be a way to deal with this common scenario.

You can reference a control within a user control by seperating the two with a dollar sign:
<asp:RequiredFieldValidator ControlToValidate="MyUserControl$ControlId" runat="server" />

Create a property on your new user control that sets the validation group on the contained validator. Then from your markup, all you need to do is just set the ValidationGroup property on the control, and that'll roll to the validators contained in the user control. You likely don't need the interface or inheriting from BaseValidator unless you are creating JUST a validation user control.
public string ValidationGroup
{
get
{
return MyRequiredFieldValidator.ValidationGroup;
}
set
{
MyRequiredFieldValidator.ValidationGroup = value;
}
}

Try adding [ValidationProperty("NameOfPropertyToBeValidated") on your user control class.

If you are planning to add lots of validation in the future it may pay off to check out Peter Blum's DES (Data Entry Suite) - it has numerous enhanced controls for data entry and validation including conditional validation scenarios and the one you are describing. Licensing is very reasonable compared to the time required to develop it yourself.

Related

How to get all validators in the page?

I thought RequiredFieldValidators, CustomValidators, and all other validators would live in Controls collection. Basically I have a User Control that has a number of validators in it, and I would like to get a handle on them to do stuff.
Page.Validators seem to return a list of IValidator objects, which are not what I am looking for.
Where can I get the list of all validators in a User Control?
The Page.Validators collection is your best bet; all validators implement IValidator, and in turn, BaseValidator, so you can use this do to that. Since the validator is a control, it's parent reference trail will contain a reference to the user control it lives in. It may require you doing something like:
if (validator.Parent.Parent.Parent.Parent is UserControl) { }
But that is the only way to figure that out. So a combination of Page.Validators, and checking the parent control tree is the only way, unless you look for specific validation groups that a validator implements, which also is another way (a property of BaseValidator, so you'll have to do a type check and cast.
There is one last potential option; you can override AddedControl, which executes on every control add, and check if the control is a validator, and then keep that control in a local collection like:
private List<BaseValidator> _vals = ..;
protected overrides void AddedControl(Control control, int index) {
if (control is BaseValidator)
_vals.Add((BaseValidator)control);
}
Then you would know which controls belong to that user control. I've done this with custom controls, not anything with user controls, so may not work exactly as I mentioned...
Since you're using ASP.NET validation controls you might be looking for a validation summary:
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.validationsummary%28v=vs.100%29.aspx
You can do quite a bit with it fitting most usage scenarios, here's a simple example:
http://asp-net-example.blogspot.com/2008/10/validationsummary-example-how-to-use.html
Alternatively, Page.Validators would provide direct access.

Using ASP.NET validators to validate Composite Control data

Background: I have a toolset of CompositeControls that I use to build forms. The controls themselves tie in to some jquery validation for basic validation tasks.
Problem: I want to make the validation of these CompositeControls more flexible by allowing developers to use the ASP.NET validators (i.e. RegExValidator, RequiredFieldValidator, CustomValidator, etc) to validate the data in one of my CompositeControls.
Example: I'd like the developers to be able to do something like this:
<asp:ValidationSummary runat=server HeaderText="There were errors on the page:" />
<custom:TextBox id='SomeTextBox' Label='Enter Name Here:' text='' runat='server' />
<asp:RequiredFieldValidator runat=server ControlToValidate=SomeTextBox ErrorMessage="Name is required."> *
</asp:RequiredFieldValidator>
I have added the "ValidationProperty" to the composite textbox, but the RequiredFieldValidator (or any ofthe other validators) don't seem to recognize the textbox or the data coming from it. The textbox (and all other custom CompositeControls I built) inherit CompositeControl, have the attribute "ValidationProperty" set to the public property that exposes the data element of the control, and contain a "string ValidationGroup" property as well.
Question: Does anybody know what else or what specifically a Composite Control requires to play nice with the ASP.NET validators (I'd prefer avoiding including instances of all the validator types in the composite control, unless of course that is necessary)?
I last looked into this in about 2005, but from what I remember, there are two separate issues here:
How the client-side validation code finds the value to validate
How the server-side validation finds the value to validate
Setting ValidationProperty is only going to affect the server-side validation, if I'm not mistaken. If you haven't already, check whether the IsValid property of the validators is set to false on the server side after you post back.
This may have changed, but I think it was also true that validation controls could only validate controls that had the same naming container as they did.
On the client side, I'm a little hazier, but I think the situation is still that the validation script will look for an element with the client ID corresponding to the server ID it was told to look for, and look for a value property on that. If you're not exposing one on the client side, it's not going to be able to find anything to validate.
If you have time, it'll help a lot to step through the validation javascript. That'll teach you a LOT about how client-side validation finds the values that it validates.
Hope this helps.

Custom TextBox Control with built-in client-side validation

I have a textbox in my application which has multiple validation on it e.g. RequiredFieldValidator, RegexValidation and CustomValidation. My page has several similar textboxes. So I just copy-paste and change id and controltovalidate properties and it is working.
Since similar tbxs are going to be used on another page as well, I think it would be nice to create my own custom TextBox control with built-in validation.
Here are two approaches I have found and tried:
1: Implement from IValidator perform my custom validation in Validate Method. As shown here: Self-Validating TextBox But it does not show how to implement client-side validation.
2: Create custom control that derives from TextBox and add asp.net built-in validators I need. As shown here:Custom TextBox. I tried the code and it works server/client side.
I like the first approach but don't know how to implement client-side validation. I know I need a client-side js function. I can do that. I know how to include my js file using Page.ClientScript class but don't know how to integrate all together and make it work.
I can create a UserControl or the second approach above but for now I am specifically looking to learn and implement client-side validation from custom control.
I am using Asp.Net 2.0. Thanks for any suggestions.
Well, you're right, you can always implement your custom server control that derives from TextBox and automatically associates a couple of validators. But usually you won't create custom controls as far as it is not explicitly needed and then through several different projects. For having client-side validaton you usually need JavaScript, but note that most of the ASP.net validation controls have their client-side validation already built-in (i.e. required field validators, range validators,...). Others (like the custom validator) allow to hook in your custom javascript.
An approach that sounds more reasonable to me is to have your TextBox controls as they are on your ASP.net page/usercontrol and to associate the validators from your code dynamically at runtime. Say in your OnInit event, you call a function RegisterRequiredValidators passing in a list of TextBoxes. I'm just thinking aloud:
public override void OnInit(...)
{
...
RegisterRequiredValidators(
txtFirstname,
txtSurname,
txtAge
}
...
}
public void RegisterRequiredValidators(params Control[] textBoxes)
{
//execute the logic of creating and attaching validators
}
That's just a stupid example, just to explain the context. In theory you can evolve this concept to register any kind of validators. We do something similar at work, by abstracting this in form of "rules" which ultimately are being rendered as ASP.net validators on the front-end.

Validate - Web User Control

I do not like to use the calendar from .NET, so I would like to have one Web User Control with 3 drop down boxes, day, month, year. [CODE DONE].
I want to be able to call this Control and initialize it with start year and end year, and with or without selected date.[CODE DONE].
This control will see if there is one valid date selected and return bool [CODE DONE].
Then in my web page I would like to able to see if that web user control is valid, in a way that I can use with the normal .NET validation (associate one required field), the problem is that I don't know where to put this code and retrieve it to the validation control on the web page. [CODE NOT DONE].
How can I do this?
There are two steps to integrating your custom server controls with the validation framework.
(1) Server side: you'll need to add a ValidationPropertyAttribute to your class, so the validation framwework knows what to look at when validating:
[ValidationProperty("SelectedDate")]
public class MyDateControl : WebControl
{
public DateTime? SelectedDate { get { ... } set { ... } }
}
(2) To hook up with client side validation, you have to make sure there's an input tag associated with your control. One way of doing that is rendering an <input type="hidden"> as the first child tag of your web control's HTML. The validation framework will pick up on that. The remaining thing to do here, is to set this hidden field through JavaScript each time your one drop downs changes.
This way, you can tie in with the existing validation controls. If you want different way to validate, you should look at a CustomValidator.
You want to use the CustomValidator control for this. See this tutorial that explains how to implement it with both a client-side and server-side version of the validation.

How To: Use AJAX in an ASP.NET Custom Server Control

Does anyone know of a good tutorial that demonstrates using an existing AJAX control extender in a Custom ASP.NET Server Control?
I do not want to build a "Custom AJAX Server Control". I want to build a Custom Server Control that uses an existing AJAX control extender.
I would like to combine an asp:TextBox, asp:ImageButton, asp:CustomValidator (with client side javascript from an embedded resource), and an ajax:CalendarExtender into one custom server control. Or has this already been created?
Any help would be greatly appreciated. Thanks.
UPDATE: Basically, I would like to create a CompositeControl that has an ajax:CalendarExtender as a child control.
Sounds like what you're after is a composite control. They are pretty much exactly like a user control only instead of using the ascx file to create the controls you create them all programmatically. The big advantage of doing this over using a user control is you end up with something you can put in an assembly and use in different projects.
A composite control can inherit from either Control or WebControl. I personally usually find Control more useful to inherit from because I usually don't need a lot of the extra stuff you get from WebControl such as the styling properties since I usually just style through a single CssClass property.
You'll also need to make sure your class implements the INamingContainer interface. This will make sure that each child control will automatically get a unique name if the control is used multiple times in the same parent container.
The most important thing to do when creating a composite control is to override Control's CreateChildControls method. All the logic for actually creating the controls should go in here. The framework will automatically make sure that this gets called at the right time in the page lifecycle.
Here's a little example:
public class MyCompositeControl : Control, INamingContainer
{
protected override void CreateChildControls()
{
Controls.Clear();
var textbox = new TextBox();
textbox.ID = "TextBox1";
Controls.Add(textbox);
if (!Page.IsPostBack || !IsTrackingViewState)
{
// make sure you set the properties after
// you add it to the parent or the viewstate
// won't save properly
textbox.MaxLength = 30;
}
var button = new Button();
button.ID = "Button1";
Controls.Add(button);
if (!Page.IsPostBack || !IsTrackingViewState)
{
button.Text = "Save";
}
}
}
I don't think ASP.NET AJAX should complicate this much. The only thing I can think of ist you'll need to make sure that you create a ScriptManager on whatever page the composite control will be added to.
There's a full example of this on the MSDN site. There's another nice example on this blog.
What you want is to build a user control and not a custom control most probably. A user control is a composite control whereas a custom control is a control built either from the ground up either derived from a basic control.
I would suggest you search on MSDN. I have seen several good articles about that topic in their magazines over the last year or two, that have been fairly thorough. But I don't have links to them and I'm too lazy to Google for you. :\

Resources