1

I'm attempting to write a try/catch, and failing obviously. I'm not sure I fully understand try/catch, but I do know that I'm having troubles wrapping my head around what I would need to happen in order to verify that a correct date is being entered submit via form. I mean, I gather it needs to be in DateTime format, not string, and should be (MM/dd/yyyy), but this try/check thing is throwing me for a loop.

Instructions: Go back to the validation code that you added in the frmPersonnel code and add a try/catch with logic to prevent an invalid date from causing a server error.

Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class frmPersonnel : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        btnSubmit.Click += new EventHandler(this.btnSubmit_Click);//event for button
    }

    private void btnSubmit_Click(object sender, EventArgs e)
    {
//DECLARATIONS
        int count = 0;
        string Msg = "You must enter a value in the following fields: <br/>  ";
        Boolean validatedState = true;
        Boolean validateEntry = false;
        DateTime endDate = new DateTime(2016, 03, 01);
        DateTime startDate = new DateTime(2016, 03, 01);


//BEGIN SERIES OF IF/ELSE FOR CONFIRMING ENTRIES         
        if (Request["txtFirstName"].ToString().Trim() == "")
            {
            //displays yellow bg for missing input
            txtFirstName.BackColor = System.Drawing.Color.Yellow;
            Msg = Msg + "First Name <br/> ";
            }//endif
        else
        {
            txtFirstName.BackColor = System.Drawing.Color.White; 
            count += 1;
        }//end else

        if (Request["txtLastName"].ToString().Trim() == "")
        {
            //displays yellow bg for missing input
            txtLastName.BackColor = System.Drawing.Color.Yellow;
            Msg = Msg + "Last Name <br/> ";
        }//endif
        else
        {
            txtFirstName.BackColor = System.Drawing.Color.White; 
            count += 1;
        }//end else

        if (Request["txtPayRate"].ToString().Trim() == "")
        {
            //displays yellow bg for missing input
            txtPayRate.BackColor = System.Drawing.Color.Yellow;
            Msg = Msg + "Pay Rate <br/>  ";
         }//endif
        else
        {
            txtFirstName.BackColor = System.Drawing.Color.White; 
            count += 1;
        }//end else

        if (Request["txtStartDate"].ToString().Trim() == "")
        {
            //displays yellow bg for missing input
            txtStartDate.BackColor = System.Drawing.Color.Yellow;
            validateEntry = false;
            Msg = Msg + "Start Date <br/>  ";
        }//endif
        else
        {
            try
                {
                //Conversion to DateTime format?
                startDate = DateTime.Parse(Request["txtStartDate"]);
                //How do I write the format I want, and when it should be checked?
                }
            catch (Exception ex)
                {
                //Exception should be caught here, not sure how to write this out though?
                }
            validateEntry = true;
        }//end else

        if (Request["txtEndDate"].ToString().Trim() == "")
        {
            //displays yellow bg for missing input
            txtEndDate.BackColor = System.Drawing.Color.Yellow;
            validateEntry = false;
            Msg = Msg + "End Date <br/>  ";
         }//endif
        else
        {
            try
            {
                //Conversion to DateTime format?
                endDate = DateTime.Parse(Request["txtEndDate"]);
                //How do I write the format I want, and when it should be checked?
            }
            catch (Exception ex)
            {
                //Exception should be caught here, not sure how to write this out though?
            }
            validateEntry = true;

        }//end else
//END SERIES OF IF/ELSE FOR CONFIRMING ENTRIES 

//START IF VALIDATE ENTRY    
        if (validateEntry == true)
        {
            if (DateTime.Compare(startDate, endDate) >= 0)
            {
                txtStartDate.BackColor = System.Drawing.Color.Yellow;
                txtEndDate.BackColor = System.Drawing.Color.Yellow;
                Msg = Msg + "Start Date <br/>" + "End Date <br/> <br/>The end date must be a later date than the start date.";
                //The Msg text will be displayed in lblError.Text after all the error messages are concatenated
                validatedState = false;
                //Boolean value - test each textbox to see if the data entered is valid, if not set validState=false. 
                //If after testing each validation rule, the validatedState value is true, then submit to frmPersonnelVerified.aspx, if not, then display error message
            }
            else //goes to this if dates are correct
            {
                validatedState = true;
                count += 2;
                txtStartDate.BackColor = System.Drawing.Color.White;
                txtEndDate.BackColor = System.Drawing.Color.White;
            }
        }
//END IF VALIDATE ENTRY

//SENDS DATA & ERROR MESSAGES
        if (count == 5 && validatedState == true)
        {
            Session["txtFirstName"] = txtFirstName.Text;
            Session["txtLastName"] = txtLastName.Text;
            Session["txtPayRate"] = txtPayRate.Text;
            Session["txtStartDate"] = txtStartDate.Text;
            Session["txtEndDate"] = txtEndDate.Text;
            Response.Redirect("frmPersonnelVerified.aspx");
            //sends to other page
        }
        else
        {
            //Writes out error messages
            Response.Write("<br/><span style = 'color: red ; position: absolute; top: 360px; left: 90px;'>" + Msg + "</span>");           
        }
//ENDS DATA AND ERROR MESSAGES


    }//end Function: private void BtnSubmit_click...

}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Sierra
  • 327
  • 4
  • 11
  • 1
    DateTime.TryParseExact? – Ziv Weissman Aug 02 '16 at 19:37
  • For starters, `DateTime.TryParse()` might be more what you're looking for, it doesn't throw an exception on a failed parse. Aside from that, what exactly is the problem that you're seeing? You have empty `catch` blocks, which means you're not actually doing anything in the event of an exception and just ignoring it entirely. Is that what you wanted to do? What's the specific issue? – David Aug 02 '16 at 19:38
  • Is that all it takes? I mean, I'll try it right now, but I'm terribly confused about how the whole try/catch thing works. – Sierra Aug 02 '16 at 19:39
  • @Sierra: It's try/catch, not try/check. And can you explain your confusion on the matter? Basically, it attempts to perform an operation (the `try` block) and, if there's an error, it provides a means of responding to that error (the `catch` block). You can catch different kinds of errors, respond in different ways, add a `finally` block, etc. – David Aug 02 '16 at 19:40
  • Oh, I just need to prevent the server error from occurring when an invalid entry is submitted. Personally, i'd prefer to have a rollback statement in there with some sql, but I think that would require quite a few additions. – Sierra Aug 02 '16 at 19:40
  • Oh, @David that's embarrassing. I did mean try/catch. – Sierra Aug 02 '16 at 19:41
  • Spend some time reading about exception handling online, or consult a book on C#. – Ian Aug 02 '16 at 19:42
  • You wouldn't persist the date to need to rollback a transaction if it didn't pass your `try` logic.. – Mark C. Aug 02 '16 at 19:42
  • @Sierra: Writing invalid data to the database *just* to roll it back seems unnecessary to me. While this code can certainly be improved (you're just beginning, don't worry about it), the structure of what you're attempting is fairly sound. Check user input for correctness, and if it's not correct respond with a friendly error message. If it is correct, proceed as intended. – David Aug 02 '16 at 19:44
  • @MarkC. That's interesting. In a previous part of this lab we used a .Rollback() on a sql transaction. Is this not the same thing? – Sierra Aug 02 '16 at 19:44
  • Why would you perform a write to a database if you had invalid data? Waste of time/resources and introduces *some* risk (thoroughly small if done correctly) – Mark C. Aug 02 '16 at 19:45
  • @MarkC. I couldn't say I know that much of what the lab is attempting to introduce by doing so, but I believe the attempt was to prevent the submission of an entry to a database that would keep the correct information with empty columns of other information, and would instead erase everything to prevent incorrect data. – Sierra Aug 02 '16 at 19:47
  • anyway, we've gotten off track. There are a lot of good answers here. Best of luck – Mark C. Aug 02 '16 at 19:47
  • @MarkC. Thanks for the time – Sierra Aug 02 '16 at 19:48
  • @David Thanks for your explanations as well! – Sierra Aug 02 '16 at 19:48

4 Answers4

2

You could use TryParse to check for a valid date

// valid Date
DateTime goodDate;
if (DateTime.TryParse("2000-02-02", out goodDate))
{
    Console.WriteLine(goodDate);
}

// not a date
DateTime badDate;
if (DateTime.TryParse("???", out badDate))
{
    Console.WriteLine(badDate);
}
else
{
    Console.WriteLine("Invalid");
}

You might also want to include the culture if you are expecting a format based on a region

string dateString;
      CultureInfo culture;
      DateTimeStyles styles;
      DateTime dateResult;    
// Parse a date and time with no styles.
      dateString = "03/01/2009 10:00 AM";
      culture = CultureInfo.CreateSpecificCulture("en-US");
      styles = DateTimeStyles.None;
      if (DateTime.TryParse(dateString, culture, styles, out dateResult))
         Console.WriteLine("{0} converted to {1} {2}.", 
                           dateString, dateResult, dateResult.Kind);
      else
         Console.WriteLine("Unable to convert {0} to a date and time.", 
                           dateString);
Lee Harris
  • 521
  • 4
  • 12
  • Thank you for the answer, just a question on region based...is there a library that needs to be added to the topic for culture? Like using culture... – Sierra Aug 02 '16 at 19:58
  • You can find the culture in the System.Globalization namespace. You could update the following row: culture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US"); – Lee Harris Aug 02 '16 at 20:05
2

From MSDN: https://msdn.microsoft.com/en-us/library/0yd65esw.aspx

When an exception is thrown, the common language runtime (CLR) looks for the catch statement that handles this exception. If the currently executing method does not contain such a catch block, the CLR looks at the method that called the current method, and so on up the call stack. If no catch block is found, then the CLR displays an unhandled exception message to the user and stops execution of the program.

The try block contains the guarded code that may cause the exception. The block is executed until an exception is thrown or it is completed successfully.

You can logically think of a try... catch... block kind of like a conditional.

For example, lets say you have this code:

string someString = "ABC";
DateTime someDate = DateTime.Parse(someString);

Obviously "ABC" is not a valid DateTime, so what happens? Your application crashes due to an unhandled exception (error).

When you wrap something in a try... catch... block, you are basically saying:

If an exception occurs in my try block, then STOP executing the code in my try block, execute the code in the catch block, and continue on like nothing happened. Otherwise, just ignore code in my catch block.

This is referred to as structured exception handling. You are anticipating "dangerous" areas of your code, and adding contingency code in case that worst-case scenario happens. Structured exception handling is especially useful for dealing with unsafe user input as well as external or unreliable systems (like external webservices).

An example:

string someString = "ABC";
DateTime someDate;

try
{
    someDate = DateTime.Parse(someString);
}
catch
{
    // someString must not have been a valid DateTime!
    // Console.WriteLine($"Hey, {someString} is not a valid DateTime!"); 
    Console.WriteLine(String.Format("Hey, {0} is not a valid DateTime!", someString)); 
}

// Code continues executing because the exception was "caught"
Community
  • 1
  • 1
DVK
  • 2,726
  • 1
  • 17
  • 20
  • You should note in your answer that your code uses [C# 6 String interpolation](https://msdn.microsoft.com/en-us/library/dn961160.aspx). It won't compile if OP isn't using C#6 – Mark C. Aug 02 '16 at 19:49
  • Not sure which version I'm using, will try to check, but I think this might be what I need. Will attempt right now. – Sierra Aug 02 '16 at 19:50
  • And thank you as well for the explanation, that really clears up a lot of my confusion. – Sierra Aug 02 '16 at 19:51
  • Obviously I was completely overthinking this. This has worked perfectly. Thank you very much. :) – Sierra Aug 02 '16 at 19:56
  • Please remember to upvote and mark as answer if this solved your problem. – DVK Aug 02 '16 at 19:57
2

Move the validateEntry = true; to within the try so you won't be setting it even if DateTime.Parse throws an exception. Your try-catchs are fine. They will catch any errors in the DateTime.Parses.

ispiro
  • 26,556
  • 38
  • 136
  • 291
1

If you really want to be exact:

        DateTime dateValue;

        var isDatePass = DateTime.TryParseExact("03/08/2002", "MM/dd/yyyy", new CultureInfo("en-US"), DateTimeStyles.None, out dateValue);

Keep in mind, you could always use upfront validation.

lucas
  • 4,445
  • 6
  • 28
  • 48