How to handle the integer textbox with value 0 - c#

I have 3 textbox
1,Age(year),
2,Age(month),
3,Age(Day))
By Default all 3 texbox value is 0(integer) which means the object assigned to each control is holding the value 0.
ibusbus.icdobus.user_month =0
ibusbus.icdobus.user_year=0
ibusbus.icdobus.user_Day=0
Now I need to validation if the user is make a empty of those textboxes.
So what I did is
public bool IsUserAgeYearisNull()
{
return (ibusbus.icdobus.user_year <= 0);
}
public bool IsUserAgeMonthisNull()
{
return (ibusbus.icdobus.user_month <= 0);
}
public bool IsUserAgeDayisNull()
{
return (ibusbus.icdobus.user_day <= 0);
}
So If user is make empty it is throwing a message.Here there is no issues
But in case User is enter year as 12 and enter 0 for both month and age.It is showing erro for month and Day that user need to enter the value.Here the user can enter 0 but it should not throw error.

Need to check all condition in all functions.
public bool IsUserAgeYearisNull()
{
if (ibusCalcWiz.icdoCalcWiz.user_age_month == 0 && ibusCalcWiz.icdoCalcWiz.user_age_day == 0)
return (ibusCalcWiz.icdoCalcWiz.user_age_year <= 0);
else
return true;
}
public bool IsUserAgeMonthisNull()
{
if (ibusCalcWiz.icdoCalcWiz.user_age_year == 0 && ibusCalcWiz.icdoCalcWiz.user_age_day == 0)
return (ibusCalcWiz.icdoCalcWiz.user_age_month <= 0);
else
return true
}
public bool IsUserAgeDayisNull()
{
if (ibusCalcWiz.icdoCalcWiz.user_age_year == 0 && ibusCalcWiz.icdoCalcWiz.user_age_month == 0)
return (ibusCalcWiz.icdoCalcWiz.user_age_day <= 0);
else
return true;
}
you can also create a common function.
public bool isValid()
{
return (busCalcWiz.icdoCalcWiz.user_age_year > 0 ||
ibusCalcWiz.icdoCalcWiz.user_age_month > 0 ||
ibusCalcWiz.icdoCalcWiz.user_age_day > 0);
}
and call from all function. Like :
public bool IsUserAgeDayisNull()
{
return isValid();
}

You can use a RangeValidator for each of TextBoxes.

Using RangeValidator as suggested earlier would be a better idea rather than writing lots of code. it will become hard to maintain the code in long run.

Related

C# - Correct way to check for nullable DateTime in if statement

I have the following code method, which is designed to check if a user is blocked temporarily after invalidating their maximum attempts (say, 10) to login in a two hour period.
public MyError ValidationMethod(MyObject myObject) {
int maxMaximumAttempts = 10;
if (myObject.Attempts >= maximumAttempts && myObject.LastAttempt.Value.AddHours(2)) < DateTime.Now)
return new MyError();
return null;
}
Both of the DateTime fields, "Attempts" and "LastAttempt" are nullable, what is the proper way to format this if statement to ensure I don't get null reference exceptions?
Null for either of the fields, should be the same result as if the if statement returned false, i.e. they haven't tried to login before. I will then return null from the method itself which symbolises, no error was found with the input.
I thought the fields being null would make the whole statement false but instead I get a null reference exception, can anyone explain why please?
Edit: I have added the full method to make the context clearer.
you can this code:
if (myObject != null && myObject.LastAttempt != null)
if (myObject.Attempts >= maximumAttempts && myObject.LastAttempt.Value.AddHours(2) < DateTime.Now)
return new myError();
or:
try
{
if (myObject.Attempts >= maximumAttempts && myObject.LastAttempt.Value.AddHours(2) < DateTime.Now)
return new myError();
}
catch(Exception ex)
{
return new myError(ex.Message);
}
Don't bother with nullables, use DateTime.MaxTime as not yet set value.
and for Attempts use 0 as not yet set value
public class myType {
// initialize myObject.LastAttempt = DateTime.MaxTime
DateTime LastAttempt = DateTime.Max;
int Attempts = 0;
/*
.... rest of the class
*/
}
public MyError ValidationMethod(MyObject myObject) {
int maxMaximumAttempts = 5;
if (myObject.Attempts >= maximumAttempts && myObject.LastAttempt != DateTime.Max && myObject.LastAttempt.AddHours(2)) < DateTime.Now)
return new MyError();
return null;
}
The nullable DateTime object has a property called HasValue, so you could write:
if (myObject.Attempts.HasValue && myObject.Attempts.Value >= maximumAttempts && myObject.LastAttempt.HasValue && myObject.LastAttempt.Value.AddHours(2) < DateTime.Now)
return new myError();
First of all, I would move these checks to the class which holds Attempts and LastAttempt fields (or at least created an extension for this class) - check Tell Don't Ask Principle
public class MyObject
{
public bool IsBlockedOn(DateTime time)
{
if (!Attempts.HasValue || !LastAttempt.HasValue)
return false;
var hasTooManyAttempts = MaximumAttempts <= Attempts.Value;
var timeoutPassed = Timeout < (time - LastAttempt.Value);
return hasTooManyAttempts && !timeoutPassed;
}
private TimeSpan Timeout = TimeSpan.FromHours(2);
private int MaximumAttempts = 10;
// other properties
}
Your if statement:
if (myObject.IsBlockedOn(DateTime.Now))
return new MyError();
The good part - this logic is now unit-testable because you can execute it with different time arguments.
Also, consider making Attempts non-nullable and initialize it with 0.

Adding String Length Validation

I am adding validation to my text string. It allows string and integer values, which is correct, but I want to require my text to be greater than 4 characters long. I've added the text.Length > 4 but this does not add any validation when entering a 2 character string. Any suggestions?
public bool IsStringInvalid(string text)
{
if (String.IsNullOrEmpty(text))
{
if (text != null && !Regex.IsMatch(text, textCodeFormat) && text.Length > 4)
{
return true;
}
}
return false;
}
Your method is called IsStringLengthInvalid, which implies that it should be returning true for invalid strings. Right now, it appears you're trying to return true only for valid strings.
Something like this should work:
public bool IsStringInvalid(string text)
{
return string.IsNullOrEmpty(text) ||
text.Length <= 4 ||
!Regex.IsMatch(text, textCodeFormat);
}
You are checking for not null condition nested inside the null condition which is logically wrong. You should do something like this.
public bool IsStringInvalid(string text)
{
if (text != null && text.Length > 4 && !Regex.IsMatch(text, textCodeFormat))
{
return true;
}
return false;
}
You have your length validation if statement nested inside your other if. If text has any data if will never reach the nested if as it will fail the first since IsNullOrEmpty will return false.
I would do something like
if (String.IsNullOrEmpty(text) || !Regex.IsMatch(text, textCodeFormat) || text.Length < 4)
{
return true;
}
return false;

Index array out of bounds

if (testModetrue)
{
try
{
Console.Write("What number do you want the roll to be set to? (1-6)");
string diceString = Console.ReadLine();
int diceCheck = int.Parse(diceString);
if ((diceCheck >= minDiceValue) || (diceCheck <= maxDiceValue))
{
diceNo = int.Parse(diceString);
}
else if ((diceCheck <= minDiceValue) || (diceCheck >= maxDiceValue))
{
Console.WriteLine("Please enter a number between 1-6.");
break;
}
}
catch (Exception)
{
Console.WriteLine("An error has occured.");
return;
}
}
This code checks to see whether the answer given doesn't go past 6 or below 1, however whenever I run it, it does it anyway then it throws the out of array error, anybody help?
int diceCheck = int.Parse(diceString);
if ((diceCheck >= minDiceValue) || (diceCheck <= maxDiceValue))
{
diceNo = int.Parse(diceString);
}
This conditional should be AND rather than OR. Also, since you're parsing the string before the conditional, you don't need to do it inside it, so you should change that part to:
int diceCheck = int.Parse(diceString);
if (diceCheck > maxDiceValue && diceCheck < minDiceValue)
{
Console.Writeline("Please write a number between 1 and 6");
break;
}
Your other if statement was also kind of redundant because you already have other variable (dicecheck) with the value, so remove it.
private const int maxDiceValue = 6;
private const int minDiceValue = 1;
Console.Write("What number do you want the roll to be set to? (1-6)");
string diceString = Console.ReadLine();
int diceCheck;
if (!int.TryParse(diceString, out diceCheck) ||
diceCheck < minDiceValue ||
diceCheck > maxDiceValue) {
Console.WriteLine("Please enter a number between 1-6.");
return;
}
// add diceCheck to array here
Lets imagine the user introduce -1.
In the first condition you are validating if -1 >= 1 which is false, but you are also validating if -1 <= 6 which is true.
Instead of && (AND ALSO) you are using || (Or Else).
Since one of the condition is always true, the validating will always return true and therefore the code will run throwing an error.

Convert String To Int in LINQ

I have a LINQ query that queries a DataTable. In the DataTable, the field is a string and I need to compare that to an integer, basically:
if ((electrical >= 100 && electrical <= 135) || electrical == 19)
{
// The device passes
}
the problem is, I am trying to do this in LINQ like this:
var eGoodCountQuery =
from row in singulationOne.Table.AsEnumerable()
where (Int32.Parse(row.Field<String>("electrical")) >= 100 &&
Int32.Parse(row.Field<String>("electrical")) <= 135) &&
Int32.Parse(row.Field<String>("electrical")) != 19 &&
row.Field<String>("print") == printName
select row;
I keep getting the exception:
Input string was not in a correct format
The main problem occurs when electrical == ""
Unfortunately, the framework doesn't provide a nice clean way to handle parsing scenarios where it fails. Of what's provided, they only throw exceptions or use out parameters, both of which does not work well with linq queries. If any one value you're parsing fails, the entire query fails and you just can't really use out parameters. You need to provide a method to handle the parsing without that does not throw and does not require using out parameters.
You can handle this in many ways. Implement it where upon failure, you return some default sentinel value.
public static int ParseInt32(string str, int defaultValue = 0)
{
int result;
return Int32.TryParse(str, out result) ? result : defaultValue;
}
Or what I would recommend, return a nullable value (null indicating it failed).
public static int? ParseInt32(string str)
{
int result;
return Int32.TryParse(str, out result) ? result : null;
}
This simplifies your query dramatically while still leaving it readable.
public bool GetElectricalStatus(string printName)
{
var query =
from row in singulationOne.Table.AsEnumerable()
where row.Field<string>("print") == printName
// using the nullable implementation
let electrical = ParseInt32(row.Field<string>("electrical"))
where electrical != null
where electrical == 19 || electrical >= 100 && electrical <= 135
select row;
return !query.Any();
}
p.s., your use of the Convert.ToInt32() method is incorrect. It is the same as calling Int32.Parse() and does not return a nullable, it will throw on failure.
I would check if the data in the column does not contain leading/trailing whitespaces - i.e. "15 " rather than "15" and if it does (or might do) trim it before trying to convert:
Int32.Parse(row.Field<String>("electrical").Trim())
BTW: not related to the error but I'd use let statement to introduce a local variable and do the conversion once:
let x = Int32.Parse(row.Field<String>("electrical").Trim())
where x >= 100...
I could not get anything to work, so I re-did the whole method:
public bool GetElectricalStatus(string printName)
{
List<object> eGoodList = new List<object>();
var eGoodCountQuery =
from row in singulationOne.Table.AsEnumerable()
where row.Field<String>("print") == printName
select row.Field<String>("electrical");
foreach (var eCode in eGoodCountQuery)
{
if (!string.IsNullOrEmpty(eCode.ToString()))
{
int? eCodeInt = Convert.ToInt32(eCode);
if (eCodeInt != null &&
(eCodeInt >= 100 && eCodeInt <= 135) || eCodeInt == 19)
{
eGoodList.Add(eCode);
}
}
}
if (eGoodList.Count() > 0)
{
return false;
}
else
{
return true;
}
}
The main problem occurs when electrical == ""
Why not make a function that does your evaluation, and call it in your Linq query. Put logic in to check the validity of the data contained within (so if you can't parse the data, it should return false)...
The function:
bool IsInRange(string text, int lower, int upper, params int[] diqualifiers)
{
int value = int.MinValue;
if (!int.TryParse(text, out value)) {
return false;
}
if (!(value >= lower && value <= upper)) {
return false;
}
if (disqualifiers != null && disqualifiers.Any(d => d == value)) {
return false;
}
return true;
}
The Linq query...
var eGoodCountQuery =
from row in singulationOne.Table.AsEnumerable()
where
IsInRange(row.Field<String>("electrical"), 100, 135, 19)
&& row.Field<String>("print") == printName
select row;

Asp.Net : Extended range validation

I'm using Asp.Net 2.0. I have a scenario where i need to check a user input against any of two ranges. For e.g. I need to check a textbox value against ranges 100-200 or 500-600. I know that i can hook up 2 Asp.Net RangeValidators to the TextBox, but that will try to validate the input against both the ranges, an AND condition,if you will. CustomValidator is an option, but how would I pass the 2 ranges values from the server-side. Is it possible to extend the RangeValidator to solve this particular problem?
[Update]
Sorry I didn't mention this, the problem for me is that range can vary. And also the different controls in the page will have different ranges based on some condition. I know i can hold these values in some js variable or hidden input element, but it won't look very elegant.
A CustomValidator should work. I'm not sure what you mean by "pass the 2 ranges values from the server-side". You could validate it on the server-side using a validation method like this:
void ValidateRange(object sender, ServerValidateEventArgs e)
{
int input;
bool parseOk = int.TryParse(e.Value, out input);
e.IsValid = parseOk &&
((input >= 100 || input <= 200) ||
(input >= 500 || input <= 600));
}
You will then need to set the OnServerValidate property of your CustomValidator to "ValidateRange", or whatever you happen to call it.
Is this the sort of thing you're after?
I do not believe this is possible using the standard RangeValidator control.
I did some searching and I believe your best solution is going to be to create your own CustomValidator control which you can include in your project to handle this scenario.
http://www.dotnetjunkies.ddj.com/Article/592CE980-FB7E-4DF7-9AC1-FDD572776680.dcik
You shouldn't have to compile it just to use it in your project, as long as you reference it properly.
You can use the RegularExpressionValidator with the ValidationExpression property set to
Edit: (whoops, 650 and 201 etc. were valid with the old pattern)
^(1\d{2}|200|5\d{2}|600)$
This will test the entered text for 100-200 and 500-600.
I extended the BaseValidator to achieve this. Its fairly simple once you understand how Validators work. I've included a crude version of code to demonstrate how it can be done. Mind you it's tailored to my problem(like int's should always be > 0) but you can easily extend it.
public class RangeValidatorEx : BaseValidator
{
protected override void AddAttributesToRender(System.Web.UI.HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
if (base.RenderUplevel)
{
string clientId = this.ClientID;
// The attribute evaluation funciton holds the name of client-side js function.
Page.ClientScript.RegisterExpandoAttribute(clientId, "evaluationfunction", "RangeValidatorEx");
Page.ClientScript.RegisterExpandoAttribute(clientId, "Range1High", this.Range1High.ToString());
Page.ClientScript.RegisterExpandoAttribute(clientId, "Range2High", this.Range2High.ToString());
Page.ClientScript.RegisterExpandoAttribute(clientId, "Range1Low", this.Range1Low.ToString());
Page.ClientScript.RegisterExpandoAttribute(clientId, "Range2Low", this.Range2Low.ToString());
}
}
// Will be invoked to validate the parameters
protected override bool ControlPropertiesValid()
{
if ((Range1High <= 0) || (this.Range1Low <= 0) || (this.Range2High <= 0) || (this.Range2Low <= 0))
throw new HttpException("The range values cannot be less than zero");
return base.ControlPropertiesValid();
}
// used to validation on server-side
protected override bool EvaluateIsValid()
{
int code;
if (!Int32.TryParse(base.GetControlValidationValue(ControlToValidate), out code))
return false;
if ((code < this.Range1High && code > this.Range1Low) || (code < this.Range2High && code > this.Range2Low))
return true;
else
return false;
}
// inject the client-side script to page
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (base.RenderUplevel)
{
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "RangeValidatorEx", RangeValidatorExJs(),true);
}
}
string RangeValidatorExJs()
{
string js;
// the validator will be rendered as a SPAN tag on the client-side and it will passed to the validation function.
js = "function RangeValidatorEx(val){ "
+ " var code=document.getElementById(val.controltovalidate).value; "
+ " if ((code < rangeValidatorCtrl.Range1High && code > rangeValidatorCtrl.Range1Low ) || (code < rangeValidatorCtrl.Range2High && code > rangeValidatorCtrl.Range2Low)) return true; else return false;}";
return js;
}
public int Range1Low
{
get {
object obj2 = this.ViewState["Range1Low"];
if (obj2 != null)
return System.Convert.ToInt32(obj2);
return 0;
}
set { this.ViewState["Range1Low"] = value; }
}
public int Range1High
{
get
{
object obj2 = this.ViewState["Range1High"];
if (obj2 != null)
return System.Convert.ToInt32(obj2);
return 0;
}
set { this.ViewState["Range1High"] = value; }
}
public int Range2Low
{
get
{
object obj2 = this.ViewState["Range2Low"];
if (obj2 != null)
return System.Convert.ToInt32(obj2);
return 0;
}
set { this.ViewState["Range2Low"] = value; }
}
public int Range2High
{
get
{
object obj2 = this.ViewState["Range2High"];
if (obj2 != null)
return System.Convert.ToInt32(obj2);
return 0;
}
set { this.ViewState["Range2High"] = value; }
}
}

Categories

Resources