https://dotnetfiddle.net/NI8H1n
¿He tenido un problema con un DateTime?
en una plantilla de afeitar en una netcoreapp3.1. La plantilla se está ejecutando a través de:
Engine.Razor.RunCompile("templateName", "templateKey" model: model);
El modelo que se pasa consta de la propiedad:
public DateTime? IssueDate { get; set; }
La línea de la navaja que arroja un error de referencia nula dentro de la plantilla es:
<td>Issue date: @(result.IssueDate.HasValue ? result.IssueDate.Value.ToString("dd/MM/yyyy") : "")</td>
El error:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot perform runtime binding on a null reference
Entonces, después de algunas depuraciones, descubrí que si cambio la línea problemática en la plantilla a:
<td>Issue date: @(result.IssueDate != null? result.IssueDate.ToString("dd/MM/yyyy") : "")</td>
Entonces estamos listos para irnos.
Entonces, la pregunta que tengo es ¿por qué no funciona la línea inicial?
Dado que su vista, copiada aquí a continuación de su Fiddle, no contiene una declaración @model
, el tipo dynamic
se está utilizando para el modelo de vista.
@(Model.SomeDate.HasValue ? Model.SomeDate.Value.ToString("dd/MM/yyyy") : "No Value")
Una vez compilada, la declaración anterior se ve como a continuación: observe el uso de dynamic
.
public override async Task ExecuteAsync() { this.Write((((dynamic)base.Model).SomeDate.HasValue) ? ((dynamic)base.Model).SomeDate.Value.ToString("dd/MM/yyyy") : "No Value" ); }
Considere la información de la documentación sobre dynamic
- Las variables de tipo dinámico se compilan en variables de tipo objeto. Por lo tanto, el tipo dinámico existe solo en tiempo de compilación, no en tiempo de ejecución.
- cualquier expresión no nula se puede convertir al tipo dinámico
Esto hace que el tipo dynamic
deba evaluar sus operaciones y tipos de datos en tiempo de ejecución.
public class SampleViewModel { public DateTime? SomeDate {get;set;} }
Dado su modelo aquí arriba, donde SomeDate
es de tipo Nullable<DateTime>
.
Cuando esa propiedad SomeDate
tendría un valor null
, obtiene el Cannot perform runtime binding on a null reference
, ya que el código intenta acceder a .HasValue
en un null
, en lugar de algo que podría haberse convertido en dynamic
(punto de viñeta 2 ).
Cuando SomeDate
tendría un valor DateTime.Now
como se muestra en su Fiddle, el enlace de tiempo de ejecución dinámico concluye que SomeDate
debe ser del tipo System.DateTime
porque DateTime.Now
no es anulable y solo una expresión no nula se puede convertir a la expresión dynamic
. tipo (punto 2).
Por lo tanto, obtiene que 'System.DateTime' does not contain a definition for 'HasValue'
, ya que DateTime
no contiene una propiedad HasValue
.
Una forma de hacer que la verificación de HasValue
funcione es incluir la declaración del modelo en la vista, ya que evita tener que usar el tipo dynamic
; consulte Fiddle actualizado .
@model HelloWorldMvcApp.SampleViewModel @(Model.SomeDate.HasValue ? Model.SomeDate.Value.ToString("dd/MM/yyyy") : "No Value")