Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DateTime validation not working despite a field with identical code working perfectly (in C# MVC, ASP.Net Core)

Edit 1

Just to Clarify a couple of points,

  • The datetime picker/script appears to be working fine, the times and dates are selectable and fill the textbox with the correct values as expected.
  • The issue occurs when a time/date is manually entered into the textbox by the user and an invalid time is entered (i.e. "78/5/2017 12:00" or "12/5/2017 12:62")
  • I've updated a typo in the code, the error is still occurring with the corrected code.

I have my fingers crossed I'm missing something obvious because this makes no sense to me. Any help you can offer would be much appreciated. I have included my code at the end of the question.

The Problem

  • I have two DateTime fields which are included in a form on a page in my application: StartTime and EndTime.
  • Both of the fields are setup and put onto the page using (what I believe to be) identical code.
  • The StartTime field works perfectly, only excepting valid times as input and displaying an error for nonsensical times such as 28:30 or 17:67 until the User corrects it.
  • The EndTime field however does not validate correctly. Bad inputs are switched back to the current Time/Date before being passed back to the controller, the controller never even sees the bad values meaning I can't catch it and return an error at that point.
  • If nonsensical values are given in both fields then the submission is prevented and both fields show a validation error which suggests that the EndTime validation does work, it just doesn't prevent form submission.

My Efforts

As I have one working field I have attempted to use that to correct the error. However I hit a stumbling block in realising that there are no differences between the two. Deciding that I must have missed something I switched the variable names round so that the StartTime would be using the EndTime code and vice versa, I did this in each of the sections below one by one hoping to find a point where the field which was working swapped. That, however, never happened. Even once the entirety of their code was switched over it was still found to be the EndTime variable/field which was broken and the StartTime variable/field which was working.

My Research

Despite spending nearly a week with this bug now I have been unable to find any similar problems online and am at a complete stumbling block as to where to go or what to try now. I have tried looking for issues caused by DateTime calendar pickers as well as validation errors in general but can't find anything of use to this situation.

This is one of the last bugs to fix before the project is completed and so any help or even ideas you can offer would be amazing.

The Code

I have included everything I could think to here that interacts with the fields in question. If I have missed anything or you need more info please let me know.

The Entity Model

I have the following two DateTime fields in my Record Entity

public partial class Record
{
    // Other entity fields
    // ....
    // ...
    // ..

    [DisplayName("Start Time")]
    [DataType(DataType.DateTime)]
    [DisplayFormat(DataFormatString = "{0:g}", ApplyFormatInEditMode = true)]
    public DateTime StartTime { get; set; }

    [DisplayName("End Time")]
    [DataType(DataType.DateTime)]
    [DisplayFormat(DataFormatString = "{0:g}", ApplyFormatInEditMode = true)]
    public DateTime EndTime { get; set; }

    // and in the constructor
    public Record()
    {
        // initialise the DateTime fields with the current DateTime,
        // adjusted for daylight savings

        BaseController b = new BaseController();
        StartTime = b.TimeNow();
        EndTime = b.TimeNow();
    }
}

For the sake of completion this is the TimeNow() function's code:

public DateTime TimeNow()
{
    TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
    DateTime t = DateTime.Now;
        
    if (tz.IsDaylightSavingTime(t))
        t = t.AddHours(1);

    return t;
}

The ViewModel

The Record entity is then included into a ViewModel as follows:

public class Home_UserAddRecord
{
    [DisplayName("Record")]
    public Record record { get; set; }

    // Other ViewModel fields
    // ....
    // ...
    // ..

    // and the blank constructor:
    public Home_UserAddRecord()
    {
        record = new Record();
        Error = false;
        ErrorMessage = string.Empty;
    }
}

The CSHTML Form

They are then included into a form on the page like so:

@using (Html.BeginForm())
{
    <div class="form-horizontal">

        <div class="form-group col-md-12">
            @Html.LabelFor(model => model.record.StartTime, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-5">
                @Html.EditorFor(model => model.record.StartTime, new { htmlAttributes = new { @Value = Model.record.StartTime.ToString("dd/MM/yyyy HH:mm"), @class = "form-control", @id = "StartDate" } })
                @Html.ValidationMessageFor(model => model.record.StartTime, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group col-md-12">
            @Html.LabelFor(model => model.record.EndTime, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-5">
                @Html.EditorFor(model => model.record.EndTime, new{ htmlAttributes = new{ @Value = Model.record.EndTime.ToString("dd/MM/yyyy HH:mm"), @class = "form-control", @id = "EndDate" } })
                @Html.ValidationMessageFor(model => model.record.EndTime, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>

    </div>
}

An Attached Script

And then finally they have a script applied to them to allow the use of a calendar picker on each input. The script looks like this:

@section Scripts{

    <script>

        var Start = new dhtmlXCalendarObject("StartDate");
        Start.setDateFormat("%d/%m/%Y %H:%i");
        Start.showToday();
        Start.attachEvent("onTimeChange", function (d) {
            var DateText = Start.getDate(true)
            document.getElementById("StartDate").value = DateText;
        });


        var End = new dhtmlXCalendarObject("EndDate");
        End.setDateFormat("%d/%m/%Y %H:%i");
        End.showToday();
        End.attachEvent("onTimeChange", function (d) {
            var DateText = End.getDate(true)
            document.getElementById("EndDate").value = DateText;
        });

    </script>
}
like image 258
Tom Eardley Avatar asked May 16 '17 11:05

Tom Eardley


1 Answers

Perhaps a suggestion is to use DateTime.TryParseExact method, which will validate the "String" representation of the date using your desired format, and will return an error when the string does not comply to your specified format. Here is code, note dateFormats are based on Australian Standard dates. You can of course add hours and minutes to this too.

Note parsedDate is a DateTime format. Usage of below is:

public void test(){
   DateTime ParsedDate;
   string SomeDate = "12-May-2017";
   if(parseDate(SomeDate, out ParsedDate))
   {
       // Date was parsed successfully, you can now used ParsedDate, e.g.
       Customer.Orders[0].DateRequired = ParsedDate;
   }
   else
   {
    // Throw an error
   }
}

And the method declaration. Use either in static class, or directly in your class.

public static bool parseDate(string theDate, out DateTime parsedDate)
        {
            string[] dateFormats = { "d-M-yy", "d-MMM-yy", "d-MMM-yyyy", "d-M-yyyy", "d/M/yy", "d/M/yyyy", "yyyy-mm-dd" };
            bool result = DateTime.TryParseExact(
                theDate,
                dateFormats,
                new CultureInfo("en-AU"),
                DateTimeStyles.None, out parsedDate);

            return result;
        } //Convert string-based date to DateTime.  Uses a variety of parse templates 
like image 199
Vinnie Amir Avatar answered Oct 30 '22 11:10

Vinnie Amir