checking field values for null - asp.net

I've been working through this for a while and I'm missing the obvious. I'm trying to make sure that if a textbox value is left blank an error isn't thrown and instead a simple message is displayed in the textbox. However, what I've got and several other methods I've tried similar to this haven't worked. I can't figure out why this isn't working and what I need to do differently.
Basics:
This is a simple calculator that allows one to enter their waist, neck, and height measurements to use in a formula that calculates their estimated body fat percentage. The calculation works properly unless a field is left blank.
Thanks for any help!
My code:
if (TBWaist.Text == null || TBNeck.Text == null || TBHeight.Text == null)
{
TBBodyFat.Text = "Value missing";
}
else
if (TBWaist.Text != null & TBNeck.Text != null & TBHeight.Text != null)
{
double waist;
double neck;
double height;
waist = Convert.ToDouble(TBWaist.Text);
neck = Convert.ToDouble(TBNeck.Text);
height = Convert.ToDouble(TBHeight.Text);
TBBodyFat.Text = Convert.ToString(String.Format("{0:p2}", ((501.5 / (1.0324 - .19077 * (Math.Log10(waist - neck)) + .15456 * (Math.Log10(height))) - 450) / 100)));
Error Message
This is the error message I get if I leave the waist textbox blank. I get the same error if I leave any of the others blank as well.
Input string was not in a correct format on line 45.
waist = Convert.ToDouble(TBWaist.Text);

I would recommend using the TryParse methods. In this way, a blank, an empty string or something that is not convertible to a string are all treated the same. Second, I would recommend adding RequiredFieldValidators and/or RegularExpressionValidators to each of the text boxes to ensure that the user enters a value and that value is numeric. In this way, the check in your event procedure acts as a last ditch check instead of requiring a PostBack for validation
protected void Button1_Click(object sender, EventArgs e)
{
//Navy Men's Body Fat Formula: %Fat=495/(1.0324-.19077(log(abdomen-neck))+.15456(log(height)))-450
//string outputString = String.Format("At loop position {0}.\n", i);
double waist;
double neck;
double height;
if ( !double.TryParse( TBWaist.Text, out waist )
|| !double.TryParse( TBNeck.Text, out neck )
|| !double.TryParse( TBHeight.Text, out height ) )
{
ErrorMessageLabel.Text = "Please ensure that each value entered is numeric.";
return;
}
var bodyFat = (501.5
/ (1.0324 - .19077 * (Math.Log10(waist - neck))
+ .15456 * (Math.Log10(height))
) - 450 ) / 100;
TBBodyFat.Text = bodyFat.ToString("P2");
}

You should test for more than just null values you have to test for empty as well
use String.IsNullOrEmpty(TBWaist.Text);

How about using a RequiredFieldValidator?
Alternatively, you can check that the value is an empty string and/or null
if (
String.IsNullOrEmpty(TBWaist.Text) ||
String.IsNullOrEmpty(TBNeck.Text) ||
String.IsNullOrEmpty(TBHeight.Text)
)

Try a compare like
if( String.IsNullOrEmpty( TBWaist.Text ) == true )
{
// error case
}
else
{
// do stuff
}

You should use String.IsNullOrEmpty() instead. Your input field values are not null, simply empty, hence the conversion fails.
protected void Button1_Click(object sender, EventArgs e)
{
//Navy Men's Body Fat Formula: %Fat=495/(1.0324-.19077(log(abdomen-neck))+.15456(log(height)))-450
//string outputString = String.Format("At loop position {0}.\n", i);
if (String.IsNullOrEmpty(TBWaist.Text) || String.IsNullOrEmpty(TBNeck.Text) || String.IsNullOrEmpty(TBHeight.Text))
{
TBBodyFat.Text = "Value missing";
}
else
{
double waist;
double neck;
double height;
waist = Convert.ToDouble(TBWaist.Text);
neck = Convert.ToDouble(TBNeck.Text);
height = Convert.ToDouble(TBHeight.Text);
TBBodyFat.Text = Convert.ToString(String.Format("{0:p2}", ((501.5 / (1.0324 - .19077 * (Math.Log10(waist - neck)) + .15456 * (Math.Log10(height))) - 450) / 100)));
}
}

Related

Getting error When dt.value length is < 4

I have this code which works fine as long as as dt.Value is different to "int".
This is the line which errors:
(dt.Value.ToLower().Substring(0, 4).Equals("date"))
It works fine if dt.Value is varchar or datetime.
I provided my suggested solution at the end of this post.
// Edit
if (e.CommandName == "Edit")
{
// Get the item
RepeaterItem Item = ((RepeaterItem)((Button)e.CommandSource).NamingContainer);
// Get buttons and repeater
Button savebtn = (Button)(Item.FindControl("btnSave"));
Button editbtn = (Button)(Item.FindControl("btnEdit"));
Repeater rFields = (Repeater)(Item.FindControl("repFields"));
// Enable my fields
foreach (RepeaterItem RI in rFields.Items)
{
// Get data type
HiddenField dt = (HiddenField)(RI.FindControl("hdnDBDataType"));
// Set controls
if (RI.FindControl("chkSetting").Visible) ((CheckBox)RI.FindControl("chkSetting")).Enabled = true;
if (RI.FindControl("ddlSetting").Visible) ((DropDownList)RI.FindControl("ddlSetting")).Enabled = true;
if (RI.FindControl("txtSetting").Visible)
{
((TextBox)RI.FindControl("txtSetting")).Enabled = true;
// Check my data type
if (dt.Value.ToLower().Substring(0, 4).Equals("date")) ((CalendarExtender)RI.FindControl("extDateTime")).Enabled = true;
}
}
}
Is this a good fix ? TIA
if(dt.Value != "int" && dt.Value.ToLower().Substring(0, 4).Equals("date"))
Substring will throw an error if the second parameter is higher than the lenght of the string. What you need to do is check the length before doing the substring or use a method like #Igor suggested in the comments.
Your suggestion to check != "int" is not fullproof if let's say somehow the value is any string less than 4 characters.
(dt.Value.Length > 3 && dt.Value.ToLower().Substring(0, 4).Equals("date"))
I will also put #Igor suggestion here because it is also fullproof:
(dt.Value.StartsWith("date", StringComparison.OrdinalIgnoreCase)

How to get an Item's Lifetime in Sitecore

I would like to show Menu items on page, based on their valid from & to dates. But before that, wanted to test the output. The _Valid to date is set to 3/17/2016 12:00 AM for the 'About us' item.
The output is About us--.
What is the right way to get the Valid from & to dates.
protected void rpMenu_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
var mainItem = (Item)e.Item.DataItem;
if (mainItem != null)
{
Response.Write(mainItem.Name + "-" + mainItem.Fields["Valid to"] + "-");
//this one did not work too
Response.Write(mainItem.Name + "-" + mainItem.Fields["_Valid to"] + "-");
}
}
You can use next constants for getting ValidTo and ValidFrom fields
mainItem.Fields[Sitecore.FieldIDs.ValidFrom] and mainItem.Fields[Sitecore.FieldIDs.ValidTo]
These constants are from Sitecore.Kernel assembly.

Depending source for drop down list

I have one drop down list in my pages that its source comes of below code. Now I like to put 1 text box adjusted on my drop down list and when I type on that, source of drop down list (DocumentNo) depend on what I type in the text box and when text box is null drop downs list shows all the (DocumentNo) , please help how I have to change my code,
protected void ddlProjectDocument_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
var query = from p in _DataContext.tblDocuments
orderby p.DocumentNo
select p;
int maxs = 0;
foreach (tblDocument v in query)
{
if (v.DocumentNo.Length > maxs)
maxs = v.DocumentNo.Length;
}
foreach (tblDocument vv in query)
{
string doctitle = vv.DocumentNo;
for (int i = vv.DocumentNo.Length; i < maxs; i++)
{
doctitle += " ";
}
doctitle += " | ";
doctitle += vv.TITLE;
// Use HtmlDecode to correctly show the spaces
doctitle = HttpUtility.HtmlDecode(doctitle);
ddlProjectDocument.Items.Add(new ListItem(doctitle, vv.DocId.ToString()));
}
}
First, I would highly recommend storing the result of that query at the beginning of the method into something like a session variable so that you don't have to continually query the database every time you hit this page.
Second, you should use the OnTextChanged event in ASP.NET to solve this problem. Put in the OnTextChanged attribute to point to a method in your code behind that will grab the query result values (now found in your session variable) and will reset what is contained in ddlProjectDocument.Items to anything that matched what was being written by using String.StartsWith():
var newListOfThings = queryResults.Where(q => q.DocumentNo.StartsWith(MyTextBox.Value));
At this point all you need to do is do that same loop that you did at the end of the method above to introduce the correct formatting.

Compare Validator for two dates

I have two labels and two text boxes, a Compare validator and a button.
I need it to compare two dates (rental date , return date ) and when the rental date is less or equal to return date are the same. No validation message.
While when when the rental date is less than the return date, display an input error message.
The compare validator has been set with :
controltocompare : txtrental,
controltovalidate: txtreturndate,
operator :greater than equal,
type:date,
errormessage: return date must be greater or equal than rental date,
I am not sure how to get the btn to display it ?
You need to set the property "CausesValidation" of your button to "true" to trigger validation on its click.
Make sure the CompareValidator has runat="server"
Create a method to display message.
private void AlertBox(string Msg)
{
string s = "alert('" + Msg + "')";
ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "ckey", s, true);
}
find the code to validate and throw alert message.
if (!String.IsNullOrEmpty(txtrental.Text) && !String.IsNullOrEmpty(txtreturndate.Text))
{
DateTime ssSD = Convert.ToDateTime(txtrental.Text);
DateTime qsED = Convert.ToDateTime(txtreturndate.Text);
int chktxtfd1_sd = ssSD.CompareTo(qsSD);
if ((chktxtfd1_sd == 0 || chktxtfd1_sd == -1) )
{
//do something bcoz condition is true
}
else
{
lvflag = false;
AlertBox("date must be greater or equal than rental date");
}
}
If you find it useful, please mark it as your answer else let me know...

Parse Credit Card input from Magnetic Stripe

Does anyone know how to parse a credit card string input from a Magnetic Card Swiper?
I tried a JavaScript parser but never got it to work. This is what the input looks like.
%BNNNNNNNNNNNNNNNN^DOE/JOHN
^1210201901000101000100061000000?;NNNNNNNNNNNNNNNN=12102019010106111001?
The N's are the credit card number.
See the Magnetic Stripe Card entry # Wikipedia:
Track one, Format B:
Start sentinel — one character (generally '%')
Format code="B" — one character (alpha only)
Primary account number (PAN) — up to 19 characters. Usually, but not
always, matches the credit card number
printed on the front of the card.
Field Separator — one character (generally '^')
Name — two to 26 characters
Field Separator — one character (generally '^')
Expiration date — four characters in the form YYMM.
Service code — three characters
Discretionary data — may include Pin Verification Key Indicator (PVKI,
1 character), PIN Verification Value
(PVV, 4 characters), Card Verification
Value or Card Verification Code (CVV
or CVK, 3 characters)
End sentinel — one character (generally '?')
Longitudinal redundancy check (LRC) — one character (Most reader devices
do not return this value when the card
is swiped to the presentation layer,
and use it only to verify the input
internally to the reader.)
I hope the data is fake, otherwise Anyone could get the:
Name
Expiration Date
CVV
And I'm not sure but I think the credit card number (or # of possibilities) can be computed using the LRC.
I did you one better: I made a video showing how to do exactly this with ASP.Net/c#:
http://www.markhagan.me/Samples/CreditCardSwipeMagneticStripProcessing
Here is the section of code that you probably care about:
protected void CardReader_OTC(object sender, EventArgs e)
{
bool CaretPresent = false;
bool EqualPresent = false;
CaretPresent = CardReader.Text.Contains("^");
EqualPresent = CardReader.Text.Contains("=");
if (CaretPresent)
{
string[] CardData = CardReader.Text.Split('^');
//B1234123412341234^CardUser/John^030510100000019301000000877000000?
PersonName.Text = FormatName(CardData[1]);
CardNumber.Text = FormatCardNumber(CardData[0]);
CardExpiration.Text = CardData[2].Substring(2, 2) + "/" + CardData[2].Substring(0, 2);
}
else if (EqualPresent)
{
string[] CardData = CardReader.Text.Split('=');
//1234123412341234=0305101193010877?
CardNumber.Text = FormatCardNumber(CardData[0]);
CardExpiration.Text = CardData[1].Substring(2, 2) + "/" + CardData[1].Substring(0, 2);
}
}
The complete code is on that website I linked above.
From what I can remember:
That is a two-track magnetic strip data - first track starts with % and ends with ?, the second track starts with ; and ends with ?. These are Start/End markers.
The first track is alphanumeric, the second track is numeric, and there is a third track which is numeric also (if my memory serves correct).
The data between the start/end markers can be variable depending on the recording density of the magnetic strip. The higher the density, the more it can be recorded on one track.
Using a regex to get at the data may not be a reliable method to pick out the information required.
And not all credit cards have exactly two tracks, some uses three tracks.
Generally for a card-not present transaction (i.e. MOTO transactions) you will need cc#, expiry and possibly the CVV (aka CVC2 etc). You can obtain the first 2 from a card-swipe as this in the track data. CVV is printed on the card.
Name on card doesn't matter so much. Unless your acquirer and the cardholder are using address verification, but you can find that between ^^, it may have white space padding which you can remove.
The part you want is track2 NNNNNNNNNNNNNNNN=1210 where NNNNN=card number PAN, and 1210 = Expiry date.
Even if track1 is empty (which sometimes it is as it's not used in processing), you will still get the ;?, so you could use the index of the second ; as start of the string and = as the end of the cc# string. With the 4 characters after the = as the expiry.
I would advise getting the card holder to sign something in record of the transaction otherwise they could dispute the card and do a charge-back.
And not all credit cards have exactly two tracks, some uses three tracks.
Only track2 is used for processing and has a standardized format.
Debit cards can't generally be processed (unless they have a visa-debit card or something).
P.S. you shouldn't store cc data in plain text, so try and keep everything in mem or strong encryption.
Try this :
https://github.com/pdamer/CardReader/blob/master/CardReader.js
Or this:
http://blog.cnizz.com/2008/10/16/javascript-snippet-for-handling-credit-card-readers/
I think that what u need
here is my code:
1st the listener to get the data.... this data needs validation which i am looking for help on. A good swipe works fine, but a bad swipe will cause an error in the parser.
$('#cc-dialog-form').keypress(function(e)
{
var charCode = e.which;
//ie? evt = e || window.event;
track_start = '%';
finished = false;
timeout = 100;
track_start_code = track_start.charCodeAt(0);
//console.log('Track_start_code: ' + track_start_code);
//console.log('keycode ' + e.keycode);
//console.log('charcode ' + charCode);
//console.log('track_start_code ' + track_start_code);
if (charCode == track_start_code)
{
collect_track_data = true;
$('#offline_cc_entry').hide();
$('#cc_online').hide();
$('#Manual_CC_DATA').hide();
$('#cc_loading_image').show();
}
if (collect_track_data)
{
if (charCode == $.ui.keyCode.ENTER)
{
//all done
//console.log( card_data);
collect_track_data = false;
$('#cc_loading_image').hide();
$('#Manual_CC_DATA').show();
//console.log("Track Data: " + card_data);
process_swipe_cc_payment(card_data);
card_data = '';
}
else
{
card_data = card_data + String.fromCharCode(charCode);
console.log(card_data);
if (e.preventDefault) e.preventDefault();
e.returnValue=false;
return false;
}
}
else
{
//i am guessing this will be regular input?
if (charCode == $.ui.keyCode.ENTER)
{
process_keyed_or_offline_CC_payment();
}
}
//console.log("which: " + e.which);
//console.log("keyCode: " + e.keyCode);
//track and collect data here?
});
And here is the parser.... note I put it all in one function so I can destroy all the variables so they are not lingering in a browser.
parse_data = true;
if (parse_data)
{
var parsed_card_data = {};
parsed_card_data['card_data'] = card_data;
var tracks = card_data.split("?");
//console.log ("tracks");
//console.log (tracks);
parsed_card_data['track1'] = tracks[0];
parsed_card_data['track2'] = tracks[1];
//if there is a third track we might find it under tracks[2]
//splitting the card data OPTION 1
var track1_parsed = tracks[0].split("^");
//console.log (track1_parsed);
//track1 data....
var card_number_track1 = track1_parsed[0].substring(2);
parsed_card_data['card_number_track1'] = card_number_track1;
var details2_1 = tracks[1].split(";");
details2_1 = details2_1[1].split("=");
var exp_date_track_1 = details2_1[1];
exp_date_track_1 = exp_date_track_1.substring(0, exp_date_track_1.length - 1);
exp_date_track_1 = exp_date_track_1.substring(2, 4) + "/" + exp_date_track_1.substring(0,2);
parsed_card_data['exp_track1'] = exp_date_track_1;
//now check if track one matches track 2...
track2_parsed = tracks[1].split("=");
card_number_track_2 = track2_parsed[0].substring(1);
parsed_card_data['card_number_track_2'] = card_number_track_2;
exp_date_track_2 = track2_parsed[1].substring(0,4);
exp_date_track_2 = exp_date_track_2.substring(2, 4) + "/" + exp_date_track_2.substring(0,2);
parsed_card_data['exp_date_track_2'] = exp_date_track_2;
var primary_account_number = card_number_track1.substring(0,1);
if(card_number_track1 == card_number_track_2 && exp_date_track_1 == exp_date_track_2)
{
//now make a security feature showing the last 4 digits only....
parsed_card_data['secure_card_number'] = "xxxx " + card_number_track1.substring(card_number_track1.length-4, card_number_track1.length);
if(card_number_track1.length == 15)
{
parsed_card_data['card_type'] = "American Express";
}
else if(primary_account_number == 4)
{
parsed_card_data['card_type'] = "Visa";
}
else if(primary_account_number == 5)
{
parsed_card_data['card_type'] = "Master Card";
}
else if(primary_account_number == 6)
{
parsed_card_data['card_type'] = "Discover";
}
else
{
parsed_card_data['card_type'] = false;
}
var names_1 = track1_parsed[1].split("/");
parsed_card_data['first_name'] = names_1[1].trim();
parsed_card_data['last_name'] = names_1[0].trim();
//console.log("return Data");
//console.log(return_data);
}
else
{
parsed_card_data = false;
}
//zero out the variables...
tracks = '';
track1_parsed = '';
card_number_track1 = '';
details2_1 = '';
exp_date_track_1 = '';
track2_parsed = '';
card_number_track_2 = '';
exp_date_track_2 = '';
primary_account_number = '';
}
if(parsed_card_data)
{
//console.log(parsed_card_data);
$('#card_type').val(parsed_card_data['card_type']);
$('#credit_card_number').val(parsed_card_data['secure_card_number']);
$('#expiration').val(parsed_card_data['exp']);
$('#card_holder').val(parsed_card_data['first_name']+ " " + parsed_card_data['last_name']);
//parsed_card_data['track1'] is basically what we want???
$('#CC_SWIPE_INSTRUCTIONS').hide();
$('#CC_DATA').hide();
$('#cc_loading_image').show();
var post_string = {};
post_string['ajax_request'] = 'CREDIT_CARD_PAYMENT';
post_string['amount'] = $('#cc_input').val();
post_string['card_data'] = parsed_card_data;
post_string['pos_sales_invoice_id'] = pos_sales_invoice_id;
post_string['pos_payment_gateway_id'] = $('#pos_payment_gateway_id').val();
post_string['line'] = 'online';
post_string['swipe'] = 'swipe';
card_data = '';
parsed_card_data = {};
var url = 'ajax_requests.php';
$.ajax({
type: 'POST',
url: url,
data: post_string,
async: true,
success: function(response)
{
$('#cc_loading_image').hide();
console.log(response);
$('#CC_RESPONSE').show();
$('#CC_RESPONSE').html(response);
//here we would update the payment table - currently we will just refresh
post_string = '';
}
});
post_string = '';
}
else
{
//error
alert("Read Error");
$( "#cc-dialog-form" ).dialog( "close" );
}

Resources