I have a webform with two custom validators:
One to validate that a string is a date. I don’t care what format, so long as it’s parseable.
Another to ensure that one date is equal to or greater than another. I just couldn’t get the compare validator to play nice with any date format.
<asp:TextBox ID="txtResourceStartDate" runat="server"
CssClass="textBox mandatory dateField" />
<asp:CustomValidator ID="valResourceStartDateIsDate" runat="server"
ControlToValidate="txtResourceStartDate" Display="None"
ErrorMessage="Start date must be a valid date"
OnServerValidate="Date_ServerValidate" />
<asp:TextBox ID="txtResourceEndDate" runat="server"
CssClass="textBox mandatory dateField" />
<asp:CustomValidator ID="valResourceEndDateIsDate" runat="server"
ControlToValidate="txtResourceEndDate" Display="None"
ErrorMessage="End date must be a valid date"
OnServerValidate="Date_ServerValidate" />
<asp:CustomValidator Display="None" Text="" ID="valForStartEndDate" runat="server"
OnServerValidate="ValidateStartEndDate"
ErrorMessage="Last day must be greater than or equal to first day" />
protected void Date_ServerValidate(object source, ServerValidateEventArgs args)
{
DateTime outDate;
args.IsValid = DateTime.TryParse(args.Value, out outDate);
}
protected void ValidateStartEndDate(object sender, ServerValidateEventArgs e)
{
e.IsValid = DateTime.Parse(txtResourceEndDate.Text) >=
DateTime.Parse(txtResourceStartDate.Text);
}
The problem is that the ValidateStartEndDate validator is firing before the Date_ServerValidate validator, so if the date is not valid, a format exception is thrown on DateTime.Parse. Obviously this validator could check for a valid date before parsing, but I’d really prefer to have a discrete validator with an appropriate message.
So the question is this: what determines the sequence with which the validators fire? Unless I’m missing something, this is not declared at the tag level.
You can't count on a certain sequence the validators will fire and also you shouldnt. You have to make sure for yourself that the order is irrelevant.
So you could
check for the valid date
simultaneously with the
Equal-Greater-Check.
First Call your IsDate-Validator's Validate()-Function and then check if it IsValid
All validators are added to the Page.Validators collection and validation runs through this collection in order. If your logic really should rely on this order: change the order of the validators in the ASPX-Page
Some interesting infos about Page-Validation: http://msdn.microsoft.com/en-us/library/aa479045.aspx
Validation control execution order is determined by the order of the controls in the ValidatorCollection returned by Page.Validators. This order is, in turn, determined by the order of the validation controls in the markup, with some exceptions (e.g. validators within data-bound controls will get added to the collection later, and so will be at the end).
If you set CausesValidation=false on your button and then trigger validation manually with Page.Validate, you can use the Add and Remove methods on the ValidatorCollection to change the execution order:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack) {
// move myValidator to the very end, so it executes last
Validators.Remove(myValidator);
Validators.Add(myValidator);
}
}
Then, later on in the triggering control:
protected void myButton_Click(object sender, EventArgs e)
{
Page.Validate();
if (!Page.IsValid) { return; }
// validation passed, proceed...
}
Disclaimer: all of this is empirical, I haven't found MSDN docs to back it up, but it seems to work.
Related
Aim: To add a session to the ASP button so I can change the CSS value based on a set of rules.
Code so far:
<asp:Button ID="btnMyDetails" runat="server" Text="My Details" CssClass="<%=Session.Item('btnMyDetails').ToString()%>" CausesValidation="False" />
Error:
The above code tries to run the session as text and not a session. I've tried with both " and ' around.
History:
I have a working version where I use lists but would like to remove this extra coding:
<li class="<%=Session.Item("btnMyDetails").ToString()%>"
<asp:Button ID="btnMyDetails" runat="server" Text="All" CssClass="Button" /></li>
Use Following:
<asp:Button ID="btnMyDetails" runat="server" Text="My Details" CssClass='<%#Session["btnMyDetails"].ToString()%>' CausesValidation="False" OnClick="btnMyDetails_Click" />
When you set value for your Session variable at that time don't forget to call DataBind method of Button that you created. if you do not call DataBind method nothing will get assigned.
for example on page_load method you set your session variable to some value,
protected void Page_Load(object sender, EventArgs e)
{
Session["btnMyDetails"] = "firstClass";
btnMyDetails.DataBind();
}
'firstClass' will be assigned as cssClass to your button.
After that if you change value of your session variable then again call DataBind method of that button. Example of Button Click event is given
protected void btnMyDetails_Click(object sender, EventArgs e)
{
Session["btnMyDetails"] = "NewClass";
btnMyDetails.DataBind();
}
Now 'NewClass' will get assigned.
I'd go a few steps to avoid depending on your session that way, tying to directly to a property of a control. At the very least I'd call a property like MyDetailsButtonCssClass in the Page class and put the logic there.
Is there a particular condition that's being changed in session that you could use to determine the class instead of putting the class name directly in session? Otherwise you could find yourself with one logical condition that changes but multiple class names that get stored in session.
I am not too familiar with custom validation. If you are willing to help, it is MUCH appreciated!
<asp:CustomValidator ID="valMatchUserInput" runat="server" ControlToValidate="tbUserInput" ErrorMessage="Please do something."> </asp:CustomValidator>
Basically, if the user input does not match (is not equal to) a specific parameter, I would like an error message to display, so nothing happens until the user fixes the error.
Thanks!
I will give you an example...
Let's say this is your validator:
<asp:CustomValidator ID="valMatchUserInput" runat="server" ControlToValidate="tbUserInput" ErrorMessage="Please do something." **ClientValidationFunction="Bla_ClientValidate" OnServerValidate="Bla_ServerValidate"**> </asp:CustomValidator>
You have to include a server-side validation and a client-side validation.
Code behind (server-side)
protected void Bla_ServerValidate(object source, ServerValidateEventArgs args)
{
//Compare your parameter here
}
Javascript (client-side)
function bla_ClientValidate(sender, e) {
// Compare your parameter here
}
It should work then
I have a text box control in asp with 3 different validators. Each validator is getting its error message from the server, and each one validates different things.
My problem is that for some values, two or more validators are firing and I'm getting more then one error message.
I would like to make some kind of priority functionality, meaning that if the first validator is firing the other two will not. Is there any way to make the validator behave like that?
I've added some code sample:
<asp:RequiredFieldValidator ID="cvRequired" runat="server" Display="Dynamic"
ControlToValidate="txtBox" />
<asp:RegularExpressionValidator ID="cvFormat" runat="server" Display="Dynamic"
ControlToValidate="txtBox" ValidationExpression="^([A-Za-z])+$" />
<asp:CustomValidator ID="cvCustom" runat="server" Display="Dynamic"
ControlToValidate="txtBox" ClientValidationFunction="validateFunction" />
I want that the format validator and the custom validator will not fire if the required validator is invalid (actually, I just want them to not showing their error message).
As I said, the error messages are from the server, so I can't really join them to one custom validator. Also, the "validateFunction" is in another js file (for re-use).
Few logic options you got to think about,
(txtPhone) having three validators.
1.RangeValidator, 2.CustomValidator 3.Regexvalidator
Say,after validation (check what it returns if validation fails/passes) and act upon that.
if(rangevalidator1 != null)
{
...somecode...
}
I ll suggest you using javascript ..
you can use a single custom validator for all three validation and you put your code in if condition according to your need.
<asp:CustomValidator runat="server" ID="cstmStartDateValidater"
ToolTip="Start date cannot be greater than equal to end date/time or less than current date/time"
ErrorMessage="*" ControlToValidate="txtStartDateTime"
ForeColor="Red" ValidationGroup="vlgMessage" SetFocusOnError="true"
onservervalidate="cstmStartDateValidater_ServerValidate" ></asp:CustomValidator>
in the .cs page
protected void cstmStartDateValidater_ServerValidate(object source, ServerValidateEventArgs args)
{
if (CompareStartDate())
{
args.IsValid = true;
}
else
{
args.IsValid = false;
}
}
you can use following link for more information :
MSDN,
Code Project
hope these will help you .
Make use of ValidatorCalloutExtender control which is available in ajax control toolkit.
Place a separate ValidatorCalloutExtender across each control,you wish to validate it.
hi all as i know that asp.net provide server side validation control which has there own built-in logic, so i want to ask here can we extend built-in logic, i means suppose we use compare validator for comparing two file at this point it will validate according to there built-in logic, but i want to add some code for compare validator, is this possible.
According to my knowledge in asp.net every control treated as class which has data and code so according to inheritance or extend can we add some code in validation control ?
It looks like you need to use
CustomValidator
You can use a custom function to define when your control passes your validation. In this case could be something like this.
void ServerValidation (object source, ServerValidateEventArgs args)
{
args.IsValid = //Define your validation here
}
CustomValidator is one option. If you rather going to implement validator similar to existing one, you can simply derive from it and override all necessary methods. But the most important method you should look for is the EvaluateIsValid.
A CustomValidator is better in situations when your logic is more likely unique. In case you want to use the logic in multiple places, I would recommend to use inheritance. It allows you to encapsulate the logic in class library if you want, CustomValidator doesn't.
In your markup:
<asp:TextBox id="Text1" runat="server" />
<asp:CustomValidator id="CustomValidator1"
ControlToValidate="Text1"
Display="Static"
ErrorMessage="Not an even number!"
ForeColor="green"
Font-Names="verdana"
Font-Size="10pt"
OnServerValidate="ServerValidation"
runat="server"/>
<asp:Button id="Button1"
Text="Validate"
OnClick="ValidateBtn_OnClick"
runat="server"/>
In the server side code:
void ValidateBtn_OnClick(object sender, EventArgs e)
{
// Display whether the page passed validation.
if (Page.IsValid)
{
Message.Text = "Page is valid.";
}
else
{
Message.Text = "Page is not valid!";
}
}
void ServerValidation(object source, ServerValidateEventArgs args)
{
try
{
// Test whether the value entered into the text box is even.
int i = int.Parse(args.Value);
args.IsValid = ((i%2) == 0);
}
catch(Exception ex)
{
args.IsValid = false;
}
}
This example is a shortened version of the one found at the documentation page for CustomValidator:
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.customvalidator.aspx
Yes you can. Like Carlos's answer link will tell you. You can put the code in the code behind.(.cs file)
I have a asp:ListView control that I bind with a List<CustomObject>.
When Editing records in this ListView control, I can always get the Unique Id of record being edited by using:
int id = Convert.ToInt32(lstView1.DataKeys[e.NewEditIndex].Value);
Is it possible to get the whole object <CustomObject> that is being edited, using any of the ListView properties?
I just figured that out,
We can get the object being edited using following code-
protected void lstView1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
ListViewDataItem objCurrentItem = (ListViewDataItem)e.Item;
**CustomObject obj = (CustomObject)objCurrentItem.DataItem;**
if (objCurrentItem.DisplayIndex == lstView1.EditIndex)
{
TextBox txtTitle = (TextBox)objCurrentItem.FindControl("txtTitle");
txtTitle.Text = obj.Title;
}
}
Here is the answer to your comment to my question:
Yes, the reason it is null in itemcommand and works fine in itemdatabound is that the location itemcommand is not correct for reading this value. You will always get the DataItem null in ItemCommand, no matter what you do. The reason lies in the control life cycle. The control gets initialized, created and then only does any other event related to the control can fire. During control creation the CreateControlHierarchy is called which then uses the DataBind event to create and databind the child controls. At that time the DataItem is live and is not null. Before that and after that it is always null, because its role lies only for that much time span.
By the way the DataItem you are looking at is the item from the related datasource that is being used to databind the listview. The datasource is used only during databinding, hence the DataItem is available only during Item Databound.
Hope this helps !
When you click on the edit for a given item in the listview the ItemCommand event gets fired. The arguments for that event tell that you can get the list item for which that event was fired. You will have to typecast that item properly to get the information you require. The itemcommand event looks like this
protected void ListView1_ItemCommand(object sender, ListViewCommandEventArgs e)
{
}
you have e.Item to use from the ListViewCommandEventArgs.
You item updating you don't have the object available for modifying. You only have the collection of the properties and their values in the new values and old values collections that you get from event arguments. I suppose you can edit the properties of the item over there. Its more or less similar to editing the object itself, because eventually these property values will get transferred to the object using reflection.
<asp:ListView runat="server" ID="list" OnItemCommand="listVideo_ItemCommand">
<ItemTemplate>
<asp:LinkButton ID="btDelVideo" runat="server" Text="Delete" OnClientClick="return confirm('Confirm delete ?');" CommandArgument='<%# Eval("KeyID") %>' CommandName="DELETE" />
<asp:LinkButton ID="btEditVideo" runat="server" Text="Edit" CommandArgument='<%# Eval("KeyID") %>' CommandName="EDIT" />
</ItemTemplate>
</asp:ListView>
protected void list_ItemCommand(object sender, ListViewCommandEventArgs e)
{
int videoId = (int)e.CommandArgument;
switch (e.CommandName)
{
case "DELETE":
//Implement Delete event
goto default;
case "EDIT":
//Implement Edit event
goto default;
default:
//Rebind listview
break;
}
}
}