【问题标题】:Working with Nullable DateTime in Custom EditorFor在自定义 EditorFor 中使用 Nullable DateTime
【发布时间】:2017-01-19 01:59:33
【问题描述】:

我正在尝试为我的 ASP.NET MVC5 页面创建自定义编辑器,但是当下面示例中的属性 TPropNullable<DateTime> 时,我收到错误消息。失败似乎发生在helper.EditorFor(Property)。这是错误:

传入字典的模型项为空,但是这个字典 需要“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);
}

编辑:为视图、视图模型和编辑器模板添加代码参考代码

视图:尝试呈现视图模型值的代码

@model MyApp.Web.ViewModels.ProductViewModel

<div class="panel panel-primary">
    <div class="panel-heading">Upgrade Details</div>
    <div class="panel-body">
        <div class="form-horizontal">
            @Html.CustomEditorFor(model => model.DateUpgraded)
        </div>
    </div>
</div>

Viewmodel:这是未呈现的Nullable&lt;DateTime&gt; 属性

public Nullable<DateTime> DateUpgraded { get; set; }

EditorTemplateDateTime的编辑器模板

@model DateTime
@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue,
        new { @class = "form-control", placeholder = ViewData.ModelMetadata.Watermark })

【问题讨论】:

  • 该消息不是由扩展方法生成的,它是因为您的视图具有@model DateTime 并且您将null 传递给它而生成的。 (并建议您使用TagBuilder 来生成您的&lt;div &gt; 元素)
  • @StephenMuecke 我添加了更多代码来显示我的视图和视图模型。我不太确定我是否遵循您提到的内容。视图模型确实包含一个可为空的日期时间属性。你能看看并扩展你之前的评论吗?
  • 您还没有给出相关信息。您显示的代码工作正常,您的扩展方法本身无法生成该错误。我最好的猜测是你也有一个EditorTemplate 代表DateTime,它是由你的helper.EditorFor(property) 代码行呈现的。首先将helper.EditorFor(property) 更改为helper.TextBoxForFor(property)。如果视图正确呈现,请显示您可能拥有的任何 EditorTemplates DateTime
  • @StephenMuecke 我尝试将 EditorFor 更改为 TextBoxFor 并呈现一个空文本框;没有错误。我为DateTime 添加了编辑器模板代码。即使我的视图模型的属性是Nullable&lt;DateTime&gt;,这会影响事情吗?
  • 是的,因为它是@model DateTime(而你通过它DateTime?)。它必须是@model DateTime?。但是您在这里的实现确实没有意义(您也可以使用扩展方法或EditorTemplate,而不是两者)。我将在 30 分钟左右添加一个更详细的答案(并展示如何使用 TagBuilder 类)

标签: c# asp.net asp.net-mvc datetime


【解决方案1】:

错误是因为您为DateTime 创建了一个自定义EditorTemplate,它在您的扩展方法中由您的helper.EditorFor(property) 调用。这会将 Nullable&lt;DateTime&gt; 的模型传递给期望模型为 DateTime(不可为空)的视图。

您可以通过将模板中的声明更改为来解决问题

@model DateTime? // nullable

但是,同时使用为简单值类型调用 EditorTemplate 的扩展方法几乎没有意义,您应该使用其中一个。

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

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());   
}

【讨论】:

  • 注意答案更新以纠正水印问题(使用了错误的元数据)
  • 是的,更新后的答案完美运行!感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多