Since your view - copied here below from your Fiddle - does not contain a @model
declaration, the type dynamic
is being used for the viewmodel.
@(Model.SomeDate.HasValue ? Model.SomeDate.Value.ToString("dd/MM/yyyy") : "No Value")
Once compiled, the above statement looks like below - notice the use of dynamic
.
public override async Task ExecuteAsync()
{
this.Write((((dynamic)base.Model).SomeDate.HasValue)
? ((dynamic)base.Model).SomeDate.Value.ToString("dd/MM/yyyy")
: "No Value"
);
}
Consider the information from the documentation about dynamic
- Variables of type dynamic are compiled into variables of type object. Therefore, type dynamic exists only at compile time, not at
run time.
- any non-null expression can be converted to the dynamic type
This makes that the type dynamic
must evaluate its operations and data types at runtime.
public class SampleViewModel
{
public DateTime? SomeDate {get;set;}
}
Given your model here above, where SomeDate
is of type Nullable<DateTime>
.
When that SomeDate
property would have a value null
, you get the Cannot perform runtime binding on a null reference
exception, since the code tries to access .HasValue
on a null
, instead on something that could have been converted to a dynamic
(bullet point 2).
When that SomeDate
would have a DateTime.Now
value as shown in your Fiddle, the dynamic runtime binding concludes that SomeDate
must be of type System.DateTime
because DateTime.Now
is not nullable and only a non-null expression can be converted to the dynamic
type (bullet point 2).
Therefore you get the 'System.DateTime' does not contain a definition for 'HasValue'
exception, since a DateTime
does not contain a HasValue
property.
One way to make the HasValue
check work, is by including the model declaration in the view, as it avoids having to use the type dynamic
- see updated Fiddle.
@model HelloWorldMvcApp.SampleViewModel
@(Model.SomeDate.HasValue ? Model.SomeDate.Value.ToString("dd/MM/yyyy") : "No Value")