Tom Eardley
Tom Eardley

Reputation: 233

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,


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

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>
}

Upvotes: 20

Views: 3198

Answers (2)

Bansari Soni
Bansari Soni

Reputation: 36

I once faced a similar issue where view was submitting the model even if validation failed. I happened to be not using ModelState.IsValid() in the controller action. Do check if this helps.

Upvotes: 0

Vinnie Amir
Vinnie Amir

Reputation: 621

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 

Upvotes: 1

Related Questions