尽管具有完全相同代码的字段(在C#MVC,ASP.Net Core中),但DateTime验证无法正常工作

Tom*_*ley 11 c# validation asp.net-mvc datetime razor

编辑1

只是为了澄清几点,

  • 日期时间选择器/脚本似乎工作正常,时间和日期是可选择的,并按预期用正确的值填充文本框.
  • 当用户手动将时间/日期输入文本框并输入无效时间时(即"78/5/2017 12:00"或"12/5/2017 12:62"),会出现此问题
  • 我更新了代码中的拼写错误,纠正后的代码仍然出现错误.

我的手指交叉,我错过了一些明显的东西,因为这对我来说毫无意义.我们非常感谢您提供的任何帮助.我在问题的最后包含了我的代码.

问题

  • 我有两个DateTime字段,它们包含在我的应用程序页面上的表单中:StartTimeEndTime.
  • 这两个字段都是使用(我相信的)相同的代码设置并放到页面上.
  • StartTime字段工作正常,仅作为输入的有效时间除外,并且在用户更正它之前显示无意义时间(例如28:30或17:67)的错误.
  • 但该EndTime字段未正确验证.在传回控制器之前,错误的输入被切换回当前时间/日期,控制器甚至从未看到错误的值意味着我无法捕获它并在那时返回错误.
  • 如果在两个字段中都给出了无意义的值,那么就会阻止提交,并且两个字段都显示验证错误,这表明EndTime验证确实有效,它只是不会阻止表单提交.

我的努力

由于我有一个工作领域,我试图用它来纠正错误.然而,我意识到两者之间没有差异,因此遇到了绊脚石.决定我必须遗漏一些东西,我将变量名称换成圆形,以便StartTime将使用EndTime代码,反之亦然,我在下面的每个部分中逐一做到这一点,希望找到一个正在交换的字段的点.然而,这从未发生过.即使整个代码被切换,它仍然被发现是EndTime被破坏的StartTime变量/字段和正在工作的变量/字段.

我的研究

尽管现在花了将近一周的时间来处理这个bug,但我还是无法在网上找到任何类似的问题,而且我现在处于一个完整的绊脚石,无论去哪里或者现在尝试什么.我一直试图寻找由DateTime日历选择器引起的问题以及一般的验证错误,但是在这种情况下找不到任何有用的东西.

这是在项目完成之前修复的最后一个错误之一,因此您可以提供的任何帮助甚至想法都是惊人的.

代码

我已经将我能想到的所有内容都包含在与相关字段交互的内容中.如果我遗漏了任何内容或您需要更多信息,请告诉我.

实体模型

我的实体中有以下两个DateTime字段Record

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

为了完成,这是TimeNow()函数的代码:

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

    if (tz.IsDaylightSavingTime(t))
        t = t.AddHours(1);

    return t;
}
Run Code Online (Sandbox Code Playgroud)

ViewModel

Record然后将该实体包含在ViewModel中,如下所示:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

CSHTML表格

然后将它们包含在页面上的表单中,如下所示:

@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>
}
Run Code Online (Sandbox Code Playgroud)

附件

然后他们最终应用了一个脚本,允许在每个输入上使用日历选择器.该脚本如下所示:

@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>
}
Run Code Online (Sandbox Code Playgroud)

Vin*_*mir 1

也许建议是使用 DateTime.TryParseExact 方法,该方法将使用您所需的格式验证日期的“字符串”表示形式,并在字符串不符合您指定的格式时返回错误。这是代码,请注意 dateFormats 基于澳大利亚标准日期。当然,您也可以添加小时和分钟。

注意 parsedDate 是日期时间格式。下面的用法是:

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
   }
}
Run Code Online (Sandbox Code Playgroud)

以及方法声明。在静态类中使用,或直接在您的类中使用。

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 
Run Code Online (Sandbox Code Playgroud)