Using C# in ASP.NET, I want to take the result of two text fields, add them when a button is pressed, and display the result. However, if one or both of the fields are empty, I don't want any result shown.
Right now I keep getting 0 as the result if both fields are empty. I'm pretty sure this is because the two input numbers (doubles) are being assigned a default 0. How can I check for empty fields?
This is my method in my controller.
[HttpPost]
public ActionResult French(FrenchModel model, string returnUrl)
{
switch (model.operation)
{
case 1:
model.result = model.numberOne + model.numberTwo;
break;
case 2:
model.result = model.numberOne - model.numberTwo;
break;
case 3:
model.result = model.numberOne * model.numberTwo;
break;
case 4:
model.result = model.numberOne / model.numberTwo;
break;
}
return View(model);
}
Doubles are value types and thus cannot be assigned to null or "empty". If you want this capability, try using a nullable double. Either Nullable<double> or double? should work.
Be aware, using a nullable value type you will need to check it for null before you use it or risk a NullReferenceException whereas double defaults to 0 if unassigned.
Use Double? ie nullable Double, its default value is null and you'll assign a value only if textbox is not empty and you can parse it.
Here's one way to determine if one or both of the fields are empty. Refactor as you need with your particular variables.
string one = txt1.Text;
string two = txt2.Text;
string result = (string.IsNullOrEmpty(one) || string.IsNullOrEmpty(two))
?string.Empty
:double.Parse(one) + double.Parse(two);
You can use if statements:
if (operand1 != 0) { // do something.. }
else { // do something.. }
You can also do this for the second operand
Related
I am not inserting any value in VOUCHER_NO column and updating it.
But it is giving me error as
Input string was not in a correct format.Couldn't store <> in VOUCHER_NO Column. Expected type is Decimal.
Below is my code
drpayinfo[0]["VOUCHER_NO"] = e.Record["VOUCHER_NO"];
Update
I am using Oracle DB and its datatype is NUMBER (10)
Seems your e.Record["VOUCHER_NO"] have some unwanted content which is not convertible to decimal. Try this way checking before assignment or conversion
if(e.Record["VOUCHER_NO"] != "")
{
drpayinfo[0]["VOUCHER_NO"] = Convert.ToDecimal(e.Record["VOUCHER_NO"]);
}
But more safer way to detect and ignore bad content is
decimal result;
if (Decimal.TryParse(e.Record["VOUCHER_NO"], out result))
{
drpayinfo[0]["VOUCHER_NO"] = result;
}
else
{
// do stuff if failed to parese
}
Based on your comments on other answers, your value is an empty string. This cannot directly be converted to a decimal. You must decide some action to take instead.
They following code will try to convert it, and take an action if not. TryParse is your friend for conversions!
decimal num = 0;
if (!Decimal.TryParse(e.Record["VOUCHER_NO"], out num))
{
//Throw some error, maybe set num to some default and assign...
//The appropriate action in this situation depends on your needs.
}
else
{
//You can safely assign the value
drpayinfo[0]["VOUCHER_NO"] = num;
}
the problem I'm having is to validate the input means putting it in a try catch which then wont pass the variable through and I'm getting this error:
Use of unassigned local variable 'MainMenuSelection'
I've validated using this method before but for some reason it's not working now, please help
//Take the menu selection
try
{
mainMenuSelection = byte.Parse(Console.ReadLine());
}
catch
{
Console.WriteLine("Please enter a valid selection");
}
switch (mainMenuSelection) //Where error is shown
Obviously user can input anything which would not be parsed as a single byte. Try out using Byte.TryParse() method which does not generate exception and just return status flag.
You can go further and add more analysis for an user input if needed:
// Initialize by a default value to avoid
// "Use of unassigned local variable 'MainMenuSelection'" error
byte mainMenuSelection = 0x00;
string input = Console.ReadLine();
// If acceptable - remove possible spaces at the start and the end of a string
input = input.Trim();
if (input.Lenght > 1)
{
// can you do anything if user entered multiple characters?
}
else
{
if (!byte.TryParse(input, out mainMenuSelection))
{
// parsing error
}
else
{
// ok, do switch
}
}
Also perhaps you just need a single character not a byte?
Then just do:
// Character with code 0x00 would be a default value.
// and indicate that nothing was read/parsed
string input = Console.ReadLine();
char mainMenuSelection = input.Length > 0 ? input[0] : 0x00;
A better method would be to use byte.TryParse(). It's made specifically for these types of scenarios.
byte b;
if (byte.TryParse("1", out b))
{
//do something with b
}
else
{
//can't be parsed
}
If you're just concerned about the input itself, you can use the Byte.TryParse Method and then handle the false boolean case instead.
byte mainMenuSelection;
if (Byte.TryParse(Console.ReadLine(), out mainMenuSelection)
{
switch(mainMenuSelection);
}
else
{
Console.WriteLine("Please enter a valid selection");
}
I'm getting the error "A switch expression or case label must be a bool, char, string, integral, enum, or corresponding nullable type" in my code at the line,
switch (job_selecter.SelectedValue)
Here's my code:
private void start()
{
switch (job_selecter.SelectedValue)
{
case 0:
head_seal_label.Text = "Ravager's Seal: Head (8)";
break;
}
}
Could anyone tell me why this is happening and how I can fix it? Thanks!
job_selecter.SelectedValue is probably an object.
private void start()
{
int index = (int)job_selecter.SelectedValue;
switch (index )
{
case 0:
head_seal_label.Text = "Ravager's Seal: Head (8)";
break;
}
}
It seems like what you really want to do is this:
switch(job_selecter.SelectedIndex)
{
case 0:
// do whatever
break;
default:
// handle default case
break;
}
You've noted in one of your responses that casting SelectedValue to string or int or whatever can cause a null reference exception if you then use it in a switch--which makes perfect sense, because it's perfectly legal for a combo box to have nothing selected, and you're going to need to account for that case. If you switch on SelectedIndex, handling -1 will allow you to handle a case of "no selection" specifically.
Of course, it's worth pointing out that switching on SelectedIndex only makes sense if the combo box contains a known, unchanging set of values. Adding or removing values will potentially cause the indices of everything in the box to change, thus breaking the switch.
SelectedValue is an object. cast it to an int in the switch.
You might have meant to use "SelectedIndex" property (a zero based number corresponding to your selection in combo OR a -1 when nothing is selected):
switch (job_selecter.SelectedIndex)
{
case 0:
head_seal_label.Text = "Ravager's Seal: Head (8)";
break;
// other cases for other Indices
case -1:
default:
// handle nothing selected...
}
You should get your SelectedIndex into an int first, to deal with this error " "A switch expression or case label must be a bool, char, string, integral, enum, or corresponding nullable type" in my code at the line":
int index;
if(!Int32.TryParse(job_selector.SelectedIndex.ToString(), out index))
{
index = -1;
}
//All your other cases here
switch(index)
{
case 0:
head_seal_label.Text = "Ravager's Seal: Head (8)";
break;
default:
head_seal_label.Text = "Some default Value";
break;
}
Working on parsing from a text box to int to get into the incrementHour method as shown.
if (txtHourPlus.Text != String.Empty)
{
time1.incrementHour(int.Parse(txtHour.Text));
}
And in the time class: (the time1 objects class)
public int incrementHour(int step)
{
if (step > 0 && hour < 24)
{
//step = step % hour;
hour = (hour + step) % 24;
time.AddHours(hour);
return hour;
}//end of if
else
{
MessageBox.Show("Please enter a positive number.");
return 0;
}//end of else
}//end of incrementHour
not sure why i'm getting this error. I'm converting it to the corrent data type. Because it accepts an int variable.
Alright well i got it to take the value (small mistake >.> Don't even wanna say it)
However as someone already said the method probably needs work because i'm trying to change the Datetime value that i get in the first place and add an hour or subtract and etc etc.
That will happen if someone has typed "foo" into the text box, for example. You should use int.TryParse instead, which lets you detect the error without an exception being thrown.
I notice that you're not actually using the return value of your method though - just like you're not using the return value of time.AddHours. You are aware that DateTime.AddHours doesn't actually modify the value you're calling it on, aren't you? (I suspect you'll need to tweak that method quite a bit, actually... there are various potential problems with it, depending on exact what you're trying to do.)
(Finally, I'd change the method name to IncrementHour to comply with .NET conventions.)
you are testing txtHourPlus for emptiness, but then parsing and passing txtHour. typo (?)
If your input isn't parsable as an integer, attempting to parse it will raise an exception. Validate or use Int32.TryParse()
Change this part of your code:
if (txtHour.Text != String.Empty)
{
int parsedValue;
if (int.TryParse(txtHour.Text, out parsedValue))
{
time1.incrementHour(parsedValue);
}
else
{
// non-numeric value was entered into the textbox - handle accordingly.
}
}
I have a class that returns an object type to a variable. The variable Must know what the real type is when operations are performed on it:
public object Data
{
get
{
switch (CriteriaID)
{
case (int)matrix2.enums.NodeTypeEnums.Enums.MultiLineText:
return (string)_Data;
case (int)matrix2.enums.NodeTypeEnums.Enums.SingleLineText:
return (string)_Data;
case (int)matrix2.enums.NodeTypeEnums.Enums.Number:
int temp = 0;
return int.TryParse((string)_Data, out temp) ? (int?)temp : null;
case (int)matrix2.enums.NodeTypeEnums.Enums.Price:
decimal temp1 = 0;
return decimal.TryParse((string)_Data, out temp1) ? (decimal?)temp1 : null;
case (int)matrix2.enums.NodeTypeEnums.Enums.PullDown:
return (string)_Data;
case (int)matrix2.enums.NodeTypeEnums.Enums.Checkbox:
bool temp2 = false;
return bool.TryParse((string)_Data, out temp2) ? (bool?)temp2 : null;
case (int)matrix2.enums.NodeTypeEnums.Enums.Date:
DateTime temp3 = DateTime.MinValue;
return DateTime.TryParse((string)_Data, out temp3) ? ((DateTime?)temp3).Value.ToString("MM/dd/yyyy") : null;
case (int)matrix2.enums.NodeTypeEnums.Enums.Link:
return (string)_Data;
case (int)matrix2.enums.NodeTypeEnums.Enums.Image:
return (string)_Data;
default:
return (string)_Data;
}
}
set
{
_Data = value;
}
}
The data property is used like this:
temp.Count() > 0 ? temp.FirstOrDefault().Data : " "
Using it like this works but I am not sure if this is the best implementation and/or the most efficient. Is their a better way to do this?
To be honest, seeing as your dealing with a finite number of possible results, you might as well stick to using a switch statement. What I would do, is change a lot of what you are doing...
Firstly, don't put any complex operations with getters or setters. You should push these out to a seperate method:
public object Data
{
get
{
return FormatData(_Data);
}
}
Secondly, you don't need to cast in your case blocks:
case (int)matrix2.enums.NodeTypeEnums.Enums.MultiLineText:
Thirdly,
temp.Count() > 0 ? temp.FirstOrDefault().Data : " "
...there are a few issues here to, for instance:
temp.Count() > 0
...will cause the entire enumerable to be enumerated, its much more efficient to do:
temp.Any()
...as it will return after it encounters the first element, next:
temp.FirstOrDefault().Data
if you are calling .Count() > 0 (or now hopefully .Any()), you can change this to .First(), as you've already established that there must be an instance for it to hit this logic path.
temp.FirstOrDefault().Data : " ";
Because your method potentially returns types other than string, the result of the complete tertiary operation can only be assigned to Object, because the compiler won't know which argument type it can be assigned to....imagine you are returning an Int32 or a String, which one?
UPDATE
Now I think about it, a really important change you should make is simply:
public object Data { get; set;}
The property should really just return the raw data. It should be outside the problem domain of the model that you present the data (and hence convert it into other types).
It looks like you are essentially writing the object out to html, so why all the work to do with formatting it? For the most part you can use .ToString() to get the string representation of the object:
temp.Any() ? temp.First().Data.ToString() : "nbsp;"
Assuming that your origin type is compatible with the destination type, you can do something like this:
public T ConvertValue<T>(object value)
{
return (T)Convert.ChangeType(value, typeof(T), null);
}
(Or if you have the Convert.ChangeType overload that does not require the IFormatProvider)
public T ConvertValue<T>(object value)
{
return (T)Convert.ChangeType(value, typeof(T));
}
And then consume it by doing
int myValueConvertedToInt = ConvertValue<int>("12345");
However, if the types are not compatiable, i.e., you try something like
int myValueConvertedToInt = ConvertValue<int>("XXX");
It will throw. Therefore, you will want to have strong validation in place on the properties you will attempt to convert. I'm partial to the System.ComponentModel.DataAnnotations attributes for attaching validation requirements to properties.