asp validator - determine if age is within range - asp.net

Using a asp validator, is there a way to verify the date of birth that is entered is within an age range, say 5 and 22 years old?
I currently do a asp:compareValidator and a asp:rangeValidator, but i need to add another level of range validation for current date against the value entered in the textbox to notify that the age is outside the range allowed (5 and 22 years old only)
thanks
tony

You could use an ASP.NET CustomValidator for this. In your ASP.NET code, you add the following control:
<asp:CustomValidator runat="server" id="ageByDateCheck"
ControlToValidate="txtDate"
OnServerValidate="CheckAgeByDate"
ErrorMessage="You are not between the ages of 5 and 22." />
And in your code-behind, you'd have a new method for checking the age.
public void CheckAgeByDate(object source, ServerValidateEventArgs args)
{
var date = DateTime.Parse(args.Value);
args.IsValid = true; //Replace this with your age check algorithm.
}
EDIT
If you're looking for client-side validation, you'll have to create some javascript to do your validation and specify it in the control's ClientValidation field. So your ASP.NET control now looks something like this:
<asp:CustomValidator runat="server" id="ageByDateCheck"
ControlToValidate="txtDate"
OnServerValidate="CheckAgeByDate"
ClientValidation="ClientValidate"
ErrorMessage="You are not between the ages of 5 and 22." />
Your probably don't have to have a different name for that, but I tend to keep things separate for code sanity.
For your javascript:
<script language="javascript">
function ClientValidate(source, arguments)
{
var date = new Date(arguments.Value); //make sure it's something javascript can parse
//validate age here
arguments.IsValid = isValid(date);
}
</script>

Related

Can I Define an Filteredtextboxextender FilterType(s) using the web.config file

So I have a scenario where I need to change the filter type of an Filteredtextboxextender based on a value in the config file in my asp.net project.
This change propagates through about 80 input forms currently.
Since my web.config value is a string I need to do an if statement on every page to define the filter type.
e.g.
If ConfigurationManager.AppSettings("SomeVariable") = "A" Then
txtLTWo_Filteredtextboxextender.FilterType = AjaxControlToolkit.FilterTypes.LowercaseLetters Or AjaxControlToolkit.FilterTypes.UppercaseLetters Or AjaxControlToolkit.FilterTypes.Numbers
ElseIf ConfigurationManager.AppSettings("SomeVariable") = "B" Then
txtLTWo_Filteredtextboxextender.FilterType = AjaxControlToolkit.FilterTypes.Numbers
Else
txtLTWo_Filteredtextboxextender.FilterType = AjaxControlToolkit.FilterTypes.Custom
txtLTWo_Filteredtextboxextender.ValidChars = "!QW"
End If
The problem here is that a change to a filter type for a particular result would have me changing every page.
I would really like a way to define it in the config file directly.
Something like this, but obviously doesn't work.
txtML_Wo_Filteredtextboxextender.FilterType = ConfigurationManager.AppSettings("FilterType")
The only way to do it that I can come up with is to keep the filter as AjaxControlToolkit.FilterTypes.Custom
And then define the string of valid characters in the config file. However this would be a large string and seems senseless when the filter has the attributes I need.
Any ideas to streamline this would be great, thanks in advance.
Hum some ideas to float here:
On page pre render (not 100% sure of the event), the you can/could inject that code.
Or you simple have a global function in a code module that fetches the config settings you have, and then use this:
this:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<ajaxToolkit:FilteredTextBoxExtender ID="TextBox1_FilteredTextBoxExtender"
runat="server" BehaviorID="TextBox1_FilteredTextBoxExtender"
TargetControlID="TextBox1"
FilterType="LowercaseLetters" >
</ajaxToolkit:FilteredTextBoxExtender>
becomes:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<ajaxToolkit:FilteredTextBoxExtender ID="TextBox1_FilteredTextBoxExtender"
runat="server" BehaviorID="TextBox1_FilteredTextBoxExtender"
TargetControlID="TextBox1"
FilterType="<%= MyFilterType() %>" >
</ajaxToolkit:FilteredTextBoxExtender>
Or say Module1.FilterType().
So, we could say have a global vb function, and then use a sever side expression in the markup settings.
I don't know what (if) those values like Filter Type "LowercaseLetters" are string or enum???
However, a server side expression in the markup could and should work.
Public Function MyFilterType() as string ???
code here to fetch the setting from config
return strSetting
End Function

ASP.NET 4.5 TextBox TextMode

It's possible to block past dates in ASP.net TextBox TextMode = "DateTime" or "Date"
I assume this is WebForms, in which case yes, you can use a RangeValidator. Like so:
<asp:TextBox runat="server" ID="dateField" />
<asp:RangeValidator runat="server" Type="Date" ControlToValidate="dateField"
MaximumValue="9999/12/28"
MinimumValue="1000/12/28"
ErrorMessage="enter valid date" />
You'll need to set the MinimumValue attribute as appropriate. You can do this from your codebehind, or an in-page <script> block:
this.rangeValidator.MinimumValue = DateTime.UtcNow.Subtract( new TimeSpan(13,0,0) ).ToString("G", CultureInfo.InvariantCulture);
Note my use of UtcNow and subtracting 13 hours to get a true, globally-acceptable, minimum date value. You might want to change this as appropriate for your application (such as restricting it to the timezone of your server provided that's what your users expect).
This post should help you
Input element specification The min attribute, if specified, must
have a value that is a valid global date and time string. The max
attribute, if specified, must have a value that is a valid global date
and time string
You will probably do this from code behind
yourTextBox.Attributes.Add("min", DateTime.Now.ToString());

asp:CustomValidator not returning 'false'

Don't know what is wrong here. This is a page developed by someone else and I am trying to fix one of the issue.
Scenario:
ASP.NET site.
Login.aspx has <asp:login> and there are three validation groups.
Login.aspx.cs is a partial class of "user_login".
Each validation group has a textbox and an associate customvalidator. All three custom validators gets triggered when something is entered in corresponding textbox but issue is only the first textbox (bound to validationgroup = 1) returns false when validation fails.
For 2nd and 3rd, the customvalidator get triggered but when there is validation issue and even after setting "args.IsValid = false;", the process continues with what needs to be executed further.
Don't know what is going on wrong here. I would like the customvalidator to return false. Worst case, are there any ways to return the control back to the 'textbox' when validation fails?
Below is the custom validator used.
<asp:CustomValidator ID="ExistingIdValidator" runat="server" ControlToValidate="NewUserName"
ValidateEmptyText="true" ValidationGroup="NewUserForm"
OnServerValidate="NewUserNameCheck_ServerValidate">
</asp:CustomValidator>
protected void NewUserNameCheck_ServerValidate(object source, ServerValidateEventArgs args)
{
CustomValidator validator = source as CustomValidator;
if (validator != null)
{
string NewuserNameValue = this.NewUserName.Text;
Guid registeredUserId = (Guid)Membership.GetUser(NewuserNameValue).ProviderUserKey;
if (registeredUserId != null)
{
validator.IsValid = false;
this.FailureText_New.Text = "This UserID already exists. Please login as existing user";
args.IsValid = false;
}
}
}
The funny thing about ASP.NET server-side validation is that it does not automatically prevent your click events from executing. It's as if the validation procedure is performed and then the results are ignored. So, the first thing to put inside your button's event is if (!Page.IsValid) return;. That's how you prevent the rest of the event from executing, and that's how you force the user to correct any mistakes on the form.

Sorting an asp:ListView bound to an EntityDataSource

I have an asp:ListView control on an ASP.NET page. It is bound to an EntityDataSource which is setup this way:
<asp:EntityDataSource ID="EntityDataSourceOrders" runat="server"
ConnectionString="name=EntitiesContext"
DefaultContainerName="EntitiesContext" EntitySetName="SOrder"
Include="Address"
EnableDelete="True" EnableInsert="True"
EnableUpdate="True">
</asp:EntityDataSource>
In SQL Server there are two tables, SOrder and Address. SOrder has a foreign key AddressID to the Address table ("an order has one address"). The address has an alphanumeric field "Name1".
In the LayoutTemplate of the ListView is a link button to sort the orders in the list by Name1 of the order's address:
<asp:LinkButton runat="server" ID="SortButtonName" Text="Name"
CommandName="Sort" CommandArgument="Address.Name1" />
If I click this button I get an EntitySqlException telling me that "'Address.Name1' could not be resolved in the current context".
Sorting by a "flat" field of the order table - for instance "OrderCode" - works:
<asp:LinkButton runat="server" ID="SortButtonOrderCode" Text="Order number"
CommandName="Sort" CommandArgument="OrderCode" />
So the exception occurs only when I try to sort by an related field in another table. I was expecting that with the Include="Address" property of the EntityDataSource sorting by fields of the related address should be possible, but it seems not.
I've made a test hack to check the query I expect the EntityDataSource to create internally:
With Linq to Entities:
using (EntitiesContext ctx = new EntitiesContext())
{
var result = from order in ctx.SOrder.Include("Address")
orderby order.Address.Name1
select order;
foreach (SOrder x in result)
{
string test=x.Address.Name1;
}
}
Or with Entity SQL:
string queryString = #"SELECT VALUE x FROM SOrder AS x
Order By x.Address.Name1";
using (EntitiesContext ctx = new EntitiesContext())
{
ObjectQuery<SOrder> query =
new ObjectQuery<SOrder>(queryString, ctx).Include("Address");
foreach (SOrder x in query.Execute(MergeOption.AppendOnly))
{
string test=x.Address.Name1;
}
}
Both works! I get a sorted result.
Now I am a bit lost how I get this sort operation working in the ListView. Does somebody have an idea what I am doing wrong here?
Thank you in advance!
I found the solution myself. It's all a matter of three missing characters: In my code above, this ...
<asp:LinkButton runat="server" ID="SortButtonName" Text="Name"
CommandName="Sort" CommandArgument="Address.Name1" />
...is WRONG and has to be replaced by:
<asp:LinkButton runat="server" ID="SortButtonName" Text="Name"
CommandName="Sort" CommandArgument="it.Address.Name1" />
Using "it." for properties of related objects seems to be necessary in contrast to flat fields. Therefore in the second example above both ways are possible:
CommandArgument="it.OrderCode" // works
CommandArgument="OrderCode" // works as well
The same for "object identities" (primary key fields) of related objects:
CommandArgument="it.Address.AddressID" // works
CommandArgument="Address.AddressID" // works as well
But again for related properties which are not identities:
CommandArgument="it.Address.Name1" // works
CommandArgument="Address.Name1" // does NOT work
Crazy, the only place where I could find (accidentally) an indication to this solution, is this video:
How Do I Use the Entity Data Source?
...especially at around 9:40 min of the video.
Associated classes may wont work CommandArguments or eg DropDownList's DataTextField value. You may use Data Transfer Objects for listing and sorting
public class OrderDTO
{
public string AddressName1 {get;set;}
}
using (EntitiesContext ctx = new EntitiesContext())
{
var result = from order in ctx.SOrder
let dto = new OrderDTO
{
AddressName1 = order.Address.Name1
//bla bla
};
orderby dto.AddressName1
select dto;
}

Is it possible to do a custom sort on a GridView

I need to sort a GridView (Not DataGridView, it's not the same thing) that is in need of a complex sort and I don't know how it can be done. I have two column, one containing a date and another containing a priority.
If the date is lesser or equal to today's date. I want to order by priority first, then by date. If the date is greater than today's date, I want to order by date first, then by priority.
Suppose totay is 2010-jan-13, some data ordered this way could look like these
date priority Explanation
----------- -------- --------------------------------------------
2010-jan-13 3 This comes first because it has the higer priority of all items whith a date <= today
2010-jan-12 2 Since this items and the next have the same priority they're ordered by date
2010-jan-13 2
2010-jan-14 5 This item and the followings have date > today, so they are ordered by date then by priority.
2010-jan-14 0
2010-jan-15 5
2010-jan-16 5
Is there anyway to sort a grid view mannually or by passing a compare functor?
edit :
The datasource is a DataTable.
You need to sort your data source, not the GridView. (Tell us your data source and we can help. Is it a DataTable, SqlDataSource, business objects?)
From Sorting Data in a GridView Web Server Control at http://msdn.microsoft.com/en-us/library/hwf94875.aspx.
Custom Sorting
If the default sort behavior is not adequate for your requirements, you can customize the grid's sorting behavior. The basic technique for custom sorting is to handle the Sorting event. In the handler, you can do the following:
Customize the sort expression that is passed to the data source control. By default, the sort expression is the name of a single column. You can modify the sort expression in the event handler. For example, if you want to sort by two columns, you can create a sort expression that includes both. You can then pass the modified sort expression to the data source control. For more information, see the GridViewSortEventArgs..::.SortExpression property.
Create your own sorting logic. For example, if you are working with a data source that does not support sorting, you can perform the sort in your own code and then bind the grid to the sorted data.
Sort Example (Not Tested and Not Using LINQ [on purpose])
Dim oDataSet As DataSet = GatherDataSet()
Dim oDataTable As DataTable = oDataSet.Tables(0)
Dim oSort1 As New DataView(oDataTable, "Date > #2010/01/13#", "Date, Priority", DataViewRowState.CurrentRows)
Dim oSort2 As New DataView(oDataTable, "Date <= #2010/01/13#", "Priority, Date", DataViewRowState.CurrentRows)
Dim oGridDataTable As DataTable
oGridDataTable = oSort1.ToTable
oGridDataTable.Merge(oSort2.ToTable)
oGridView.DataSource = oGridDataTable
'...
'you can then merge any changes back into the data set, if needed
oDataSet.Merge(oGridDataTable)
Salut Mathieu,
Assuming you are using a DataSource and each element is a class (instead of say, a datarow), you could implement IComparable to your class. It adds the CompareTo method in which you decide how each element compares to each other.
class DatePriority: IComparable
{
private DateTime date;
public DateTime Date
{
get { return date; }
}
private int priority;
public int Priority
{
get { return priority; }
}
public DatePriority(DateTime date, int priority)
{
this.date = date;
this.priority = priority;
}
public int CompareTo(object obj)
{
if (obj is DatePriority)
{
DatePriority comparedDatePriority = obj as DatePriority;
// Comparison logic
// If the compared elements are today or before today, order by priority in descending order. Same priorities are ordered by date in ascending order
// If the compared elements are for the future, order by date in ascending order. Same dates are order by priority in descending order
if ((this.Date <= DateTime.Today && comparedDatePriority.Date <= DateTime.Today))
{
if (Priority == comparedDatePriority.Priority)
return Date.CompareTo(comparedDatePriority.Date);
else
return -Priority.CompareTo(comparedDatePriority.Priority);
}
else
{
if (Date == comparedDatePriority.date)
return -Priority.CompareTo(comparedDatePriority.Priority); // Descending order
else
return Date.CompareTo(comparedDatePriority.Date);
}
}
throw new ArgumentException("Not a DatePriority");
}
}
Yes, You can do it. Here's how you do that.
Assuming you have a GridView which calls for records from a BusinessLayer method. I will take example of UserManager as business-layer proxy class.
[DataObjectAttribute()]
public static class UserManager
{
[DataObjectMethod(DataObjectMethodType.Select, true)]
public static UserCollection GetUsers()
{
return UserDB.GetAll();
}
[DataObjectMethod(DataObjectMethodType.Select, false)]
public static UserCollection GetUsers(string sortExpression)
{
UserCollection users = UserDB.GetAll();
users.Sort(new EntityComparer<User>(sortExpression));
return users;
}
}
Look at this line of code in over-loaded GetUsers method.
users.Sort(new EntityComparer<User>(sortExpression));
I have written a Generic Comparer implementation for my business objects. EntityComparer is just a generic class that implements IComparer interface. You can write your own Comparer implementation [that implements IComparer interface] and call it as the code above.
Here's how my GridView looks like..
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataSourceID="ObjectDataSource1">
<Columns>
<asp:BoundField DataField="Id" HeaderText="Id" SortExpression="Id" />
<asp:BoundField DataField="UserName" HeaderText="UserName"
SortExpression="UserName" />
<asp:BoundField DataField="Password" HeaderText="Password"
SortExpression="Password" />
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
<asp:BoundField DataField="Email" HeaderText="Email" SortExpression="Email" />
<asp:BoundField DataField="CompanyName" HeaderText="CompanyName"
SortExpression="CompanyName" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetUsers"
TypeName="FilePark.BusinessLayer.UserManager"></asp:ObjectDataSource>
Also note that GridView will pass the sortExpression upon postback and call the overloaded method.
Sort procedure of dataGrinView uses Sort procedure of data source.
To manually sort data create class that implements IBindingListView, implement it sort method like you want and use this class as DataSource in DataGridView

Resources