C# 在自定义EditorFor中使用可为空的DateTime

C# 在自定义EditorFor中使用可为空的DateTime,c#,asp.net,asp.net-mvc,datetime,C#,Asp.net,Asp.net Mvc,Datetime,我试图为我的ASP.NET MVC5页面创建一个自定义编辑器,但是当下面示例中的属性TProp为Nullable时,我收到一个错误。故障似乎发生在helper.EditorFor(属性)上。以下是错误: 传递到字典中的模型项为null,但此字典 需要类型为“System.DateTime”的非空模型项 代码如下: public static IHtmlString CustomEditorFor<TModel, TProp>(this HtmlHelper<TModel>

我试图为我的ASP.NET MVC5页面创建一个自定义编辑器,但是当下面示例中的属性
TProp
Nullable
时,我收到一个错误。故障似乎发生在
helper.EditorFor(属性)
上。以下是错误:

传递到字典中的模型项为null,但此字典 需要类型为“System.DateTime”的非空模型项

代码如下:

public static IHtmlString CustomEditorFor<TModel, TProp>(this HtmlHelper<TModel> helper,
    Expression<Func<TModel, TProp>> property)
{
    var htmlString =
        "<div class=\"form-group\">" +
            helper.LabelFor(property) +
            "<div class=\"col-md-10\">" +
                helper.EditorFor(property) +
                helper.ValidationMessageFor(property) +
            "</div>" +
        "</div>"
        ;
    return new HtmlString(htmlString);
}

引发错误的原因是您为
DateTime
创建了一个自定义
EditorTemplate
,它由您的
helper.EditorFor(属性)
在扩展方法中调用。这会将
可为null的模型传递给一个视图,该视图需要
日期时间
(不可为null)的模型

您可以通过将模板中的声明更改为

@model DateTime? // nullable
但是,对简单值类型同时使用调用
EditorTemplate
的扩展方法没有什么意义,您应该使用其中一种方法

使用扩展方法,您的代码将是(注意,这使用了推荐的
TagBuilder
类来生成html)

public static IHtmlString CustomEditorFor(此HtmlHelper帮助程序,表达式属性)
{
var name=ExpressionHelper.GetExpressionText(属性);
var metadata=modelmetada.FromLambdaExpression(属性,helper.ViewData);
var formatString=metadata.DisplayFormatString;
var watermark=metadata.watermark;
StringBuilder html=新的StringBuilder();
Append(helper.TextBoxFor(property,formatString,new{@class=“form control”,placeholder=watermark}));
Append(helper.ValidationMessageFor(property));
标记生成器容器=新标记生成器(“div”);
容器。添加CSSClass(“col-md-10”);
container.InnerHtml=html.ToString();
html=新的StringBuilder();
Append(helper.LabelFor(property));
Append(container.ToString());
容器=新标记生成器(“div”);
container.AddCssClass(“表单组”);
container.InnerHtml=html.ToString();
返回MvcHtmlString.Create(container.ToString());
}

该消息不是由扩展方法生成的,它的生成是因为您的视图具有
@model DateTime
并且您将
null
传递给它。(建议您使用
TagBuilder
生成
元素)@StephenMuecke我添加了更多代码来显示我的视图和视图模型。我不太确定我是否明白你所说的。viewmodel不包含可为空的datetime属性。你能看看你以前的评论吗?你还没有提供相关信息。您显示的代码工作正常,扩展方法本身无法生成该错误。我猜您也有一个
EditorTemplate
for
DateTime
,它是由您的
helper.EditorFor(property)
代码行呈现的。首先将
helper.EditorFor(属性)
更改为
helper.TextBoxForFor(属性)
。如果视图呈现正确,则显示您的
日期时间
@StephenMuecke可能具有的任何
编辑器或模板
。我尝试将
EditorFor
更改为
TextBoxFor
,它呈现了一个空文本框;没有错误。我已经为
DateTime
添加了编辑器模板代码。即使我的viewmodel的属性是可为
null的
,这是否会影响一些事情?是的,因为它的
@model DateTime
(以及您传递它的
DateTime?
)。它必须是
@model DateTime?
。但是您在这里的实现实际上毫无意义(您可以使用扩展方法或
EditorTemplate
,而不是两者都使用)。我将在30分钟左右添加一个更详细的答案(并展示如何使用
TagBuilder
类)。注意:答案更新可以纠正水印问题(使用了错误的元数据)。是的,更新后的答案非常有效!谢谢你的帮助!
public Nullable<DateTime> DateUpgraded { get; set; }
@model DateTime
@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue,
        new { @class = "form-control", placeholder = ViewData.ModelMetadata.Watermark })
@model DateTime? // nullable
public static IHtmlString CustomEditorFor<TModel, TProp>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProp>> property)
{
    var name = ExpressionHelper.GetExpressionText(property);
    var metadata = ModelMetadata.FromLambdaExpression(property, helper.ViewData);
    var formatString = metadata.DisplayFormatString;
    var watermark = metadata.Watermark;

    StringBuilder html = new StringBuilder();
    html.Append(helper.TextBoxFor(property, formatString, new { @class = "form-control", placeholder = watermark }));
    html.Append(helper.ValidationMessageFor(property));
    TagBuilder container = new TagBuilder("div");
    container.AddCssClass("col-md-10");
    container.InnerHtml = html.ToString();
    html = new StringBuilder();
    html.Append(helper.LabelFor(property));
    html.Append(container.ToString());
    container = new TagBuilder("div");
    container.AddCssClass("form-group");
    container.InnerHtml = html.ToString();
    return MvcHtmlString.Create(container.ToString());   
}