我正在尝试显示一个允许用户为某人输入新作业的表单。我正在使用DateTime.cshtml EditorTemplate来处理赋值的DateTime值。不可为空的DateTime工作正常。可空的DateTime导致“InvalidOperationException:Nullable对象必须具有值”。
我有一个简单的viewmodel,如下所示:
AssignmentViewModel.cs:
public Person Person { get; set; }
public Assignment NewAssignment { get; set; }
Assignment.cs包含:
public DateTime AssignmentStartDate { get; set; }
public DateTime? AssignmentEndDate { get; set; }
我的AssignmentController Create()方法如下所示:
public ViewResult Create(int personId)
{
Person person = personRepository.GetPersonById(personId);
var newAssignment = new AssignmentViewModel { Person = person, NewAssignment = new Assignment() };
return View(newAssignment);
}
我的Create.cshtml视图如下所示:
@model AssignmentViewModel
@using (Html.BeginForm("Create", "Assignment"))
{
@Html.Hidden("NewAssignment.PersonId", Model.Person.PersonId)
@Html.LabelFor(x => x.NewAssignment.AssignmentStartDate):
@Html.EditorFor(x => x.NewAssignment.AssignmentStartDate.Date, new { cssClass = "datePicker" })
<br />
@Html.LabelFor(x => x.NewAssignment.AssignmentEndDate):
@Html.EditorFor(x => x.NewAssignment.AssignmentEndDate.Value.Date, new { cssClass = "datePicker" })
<br />
<input type="submit" value="Send />
}
My DateTime.cshtml EditorTemplate看起来像:
@model DateTime?
@{
String modelValue = "";
if (Model.HasValue)
{
if (Model.Value != DateTime.MinValue)
{
modelValue = Model.Value.ToShortDateString();
}
}
}
@Html.TextBox("", modelValue, new { @class = "datePicker" })
当我尝试加载Create视图时,我在“@ Html.EditorFor(x =&gt; x.NewAssignment.AssignmentEndDate.Value)”行中得到了上述异常。
您可能想知道我为什么要传递AssignmentEndDate.Value.Date而不是仅传递AssignmentEndDate;原因是因为我试图达到将DateTime拆分为Date和TimeOfDay字段并将其与DateTimeModelBinder重新组合的程度。我正在使用与shown here和here类似的技术。
我可以通过更改我的控制器Create()方法来绕过错误,将AssignmentEndDate设置为DateTime.MinValue来实例化ViewModel,但对于可以为空的DateTime来说这似乎完全错误:
var newAssignment = new AssignmentViewModel
{
Person = person,
NewAssignment = new Assignment { AssignmentEndDate = DateTime.MinValue }
};
在通过为可空的DateTime提供值“绕过”错误之后发生了一些奇怪的事情;不需要的可空DateTime属性(AssignmentEndDate.Date)无法通过客户端验证。尝试提交表单会以红色突出显示该字段。
我该如何正确处理?
答案 0 :(得分:5)
问题是您尝试检索AssignmentEndDate.Value.Date
,但AssignmentEndDate
是null
,这会导致此错误。
由于您的编辑器模板接受DateTime?
,因此您应该传递AssignmentEndDate
。换句话说,从视图中删除.Value.Date
:
@Html.EditorFor(x => x.NewAssignment.AssignmentEndDate, new { cssClass = "datePicker" })
由于您的编辑器模板使用ToShortDateString()
,因此无需&#34;截断&#34;从该日期开始的时间。
关于你想要分开&#34;日期&#34;和&#34;时间&#34;编辑:
你可以这两种方式做到这一点。
1 - 您当前的DateTime?
编辑器会为Model.Value.Date
呈现一个字段,因此您只需将其扩展为同时为Model.Value.TimeOfDay
呈现字段即可。例如:
@{
DateTime? modelDate = (Model == null) ? (DateTime?)null : Model.Value.Date;
TimeSpan? modelTime = (Model == null) ? (TimeSpan?)null : Model.Value.TimeOfDay;
}
@Html.TextBox(..., modelDate, new{@class="datePicker"})
@Html.TextBox(..., modelTime, new{@class="timePicker"})
2 - 您可以将上述功能拆分为2个独立的编辑器,&#34; DateOnly&#34;和#34; TimeOnly&#34;。然后,更新您的视图以调用两个编辑器:
@Html.EditorFor(x => x.NewAssignment.AssignmentEndDate, "DateOnly")
@Html.EditorFor(x => x.NewAssignment.AssignmentEndDate, "TimeOnly")
选择取决于您,是否要将日期和时间部分分开或分开,但这就是我解决此问题的方法。
答案 1 :(得分:2)
在Shared / DisplayTemplate文件夹中创建DateTime.cshtml
@model Nullable<DateTime>
@(Model != null ? string.Format(ViewData.ModelMetadata.DisplayFormatString ?? "{0:d}", Model) : string.Empty)
这支持在找到时使用的数据注释中的元数据。
答案 2 :(得分:0)
UPDATE:GetValueOrDefault将其视为DateTime,因此所需的Field验证器将被附加,因为原始表达式是针对日期时间而不是可以为空的日期时间。
与提问者一样,我也使用了DateTimeModelBinder: Here's the Link
这就是我解决类似情况的方法:
@Html.EditorFor(x => x.NewAssignment.AssignmentEndDate.GetValueOrDefault().Date)
这就是我的DateTime EditorTemplate的样子:
@model DateTime
@Html.TextBox("", Model != default(DateTime) ? Model.ToShortDateString() : String.Empty, new { @class = "datepicker", @maxlength = "10" })