Razor模板中的可空日期时间错误
c#
更新
所以看起来这也可以在 .NET 4.7.2 中复制:
https://dotnetfiddle.net/NI8H1n
原来的
我DateTime?在 netcoreapp3.1 中的剃刀模板中遇到了问题。模板正在运行:
Engine.Razor.RunCompile("templateName", "templateKey" model: model);
传递的模型包含以下属性:
public DateTime? IssueDate { get; set; }
在模板中抛出空引用错误的剃刀线是:
<td>Issue date: @(result.IssueDate.HasValue ? result.IssueDate.Value.ToString("dd/MM/yyyy") : "")</td>
错误:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot perform runtime binding on a null reference
所以经过一些调试,我发现如果我将模板中的有问题的行更改为:
<td>Issue date: @(result.IssueDate != null? result.IssueDate.ToString("dd/MM/yyyy") : "")</td>
然后我们就可以走了。
所以我的问题是为什么初始行不起作用?
回答
由于您的视图(从 Fiddle 下面复制到此处)不包含@model声明,因此该类型dynamic正用于视图模型。
@(Model.SomeDate.HasValue ? Model.SomeDate.Value.ToString("dd/MM/yyyy") : "No Value")
编译后,上面的语句如下所示 - 注意dynamic.
public override async Task ExecuteAsync()
{
this.Write((((dynamic)base.Model).SomeDate.HasValue)
? ((dynamic)base.Model).SomeDate.Value.ToString("dd/MM/yyyy")
: "No Value"
);
}
考虑文档中的信息dynamic
- 动态类型的变量被编译成对象类型的变量。因此,类型 dynamic 仅存在于编译时,而不存在于运行时。
- 任何非空表达式都可以转换为动态类型
这使得该类型dynamic必须在运行时评估其操作和数据类型。
public class SampleViewModel
{
public DateTime? SomeDate {get;set;}
}
鉴于您在上面的模型, whereSomeDate是 type Nullable<DateTime>。
当该SomeDate属性具有 value 时null,您会收到Cannot perform runtime binding on a null reference异常,因为代码尝试访问.HasValuea null,而不是可能已转换为 a 的内容dynamic(要点2)。
当它SomeDate具有DateTime.Now如 Fiddle 中所示的值时,动态运行时绑定得出结论,SomeDate必须是类型,System.DateTime因为DateTime.Now不可为空,并且只有非空表达式可以转换为该dynamic类型(第 2 点)。
因此您会得到'System.DateTime' does not contain a definition for 'HasValue'异常,因为 aDateTime不包含HasValue属性。
进行HasValue检查的一种方法是在视图中包含模型声明,因为它避免了必须使用类型dynamic- 请参阅更新的 Fiddle。
@model HelloWorldMvcApp.SampleViewModel
@(Model.SomeDate.HasValue ? Model.SomeDate.Value.ToString("dd/MM/yyyy") : "No Value")