尽管具有相同代码的字段运行良好(在 C# MVC 中,ASP.Net Core 中),但 DateTime 验证不起作用



>Edit 1

只是为了澄清几点,

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

我的手指交叉了,我错过了一些明显的东西,因为这对我来说毫无意义。您能提供的任何帮助将不胜感激。我已经在问题的末尾包含了我的代码。

问题所在

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

我的努力

由于我有一个工作字段,因此我试图使用它来纠正错误。然而,我遇到了一个绊脚石,意识到两者之间没有区别。决定我一定错过了什么,我切换了变量名称,以便StartTime将使用EndTime代码,反之亦然,我在下面的每个部分中一一执行此操作,希望找到一个点正在工作的字段交换。然而,这从未发生过。即使他们的整个代码被切换,仍然发现是EndTime变量/字段被破坏,StartTime变量/字段正在工作。

我的研究

尽管现在花了将近一周的时间处理此错误,但我无法在网上找到任何类似的问题,并且对于现在去哪里或尝试什么完全处于绊脚石。我尝试寻找由DateTime日历选择器引起的问题以及一般的验证错误,但找不到任何对这种情况有用的东西。

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

《守则》

我在这里包含了我能想到的与相关领域交互的所有内容。如果我错过了什么,或者您需要更多信息,请告诉我。

实体模型

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

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();
}
}

为了完成起见,这是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;
}

The ViewModel

然后,Record实体将包含在视图模型中,如下所示:

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

CSHTML Form

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

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

附加脚本

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

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

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

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

和方法声明。 可以在静态类中使用,也可以直接在类中使用。

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 

我曾经遇到过类似的问题,即使验证失败,视图也会提交模型。我碰巧没有在控制器操作中使用ModelState.IsValid()。请检查这是否有帮助。

最新更新