【问题标题】:C# MVC 4 ViewModel not accepting null DateTimeC# MVC 4 ViewModel 不接受 null DateTime
【发布时间】:2013-11-27 14:03:27
【问题描述】:

我在这里学习 C# 和 mvc4 有点麻烦。

问题出现在我的应用程序的过滤器部分。 我有一个 ViewModel,它可以获取数据库的“Listar_Produtos”列表,以及一些用于搜索选项的字段。

我打算做的是让过滤器接受任何字段,即使它是空值。因为我会根据这些参数制作过滤器。

我有一个视图模型:

using Foolproof;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace Ecommerce.Models.Repository
{
    public class Produto_Repository
    {
        public class Index_Listar_Produtos
        {
            public List<Listar_Produto> Index_List_Produto { get; set; }

            [Display(Name = "Data de Cadastro Inicial")]
            [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
            public Nullable<DateTime> CadastroInicialData { get; set; }

            [Display(Name = "Data de Cadastro Final")]
            [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
            [GreaterThanOrEqualTo("CadastroInicialData", ErrorMessage = "\"Data Inicial\", deve ser maior que \"Data Final\"")]
            public Nullable<DateTime> CadastroFinalData { get; set; }
        }
    }
}

我有以下观点:

<td>
    @Html.LabelFor(Model => Model.CadastroInicialData)<br />
    @Html.TextBoxFor(Model => Model.CadastroInicialData, "{0:dd/MM/yyyy}")
    @Html.ValidationMessageFor(Model => Model.CadastroInicialData)
</td>
<td>
    @Html.LabelFor(Model => Model.CadastroFinalData)<br />
    @Html.TextBoxFor(Model => Model.CadastroFinalData, "{0:dd/MM/yyyy}")
    @Html.ValidationMessageFor(Model => Model.CadastroFinalData)
</td>

在我的控制器中,我有:

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Filtro(Produto_Repository.Index_Listar_Produtos ViewModel)
{
    if (!ModelState.IsValid)
    {
        Produto_Repository.Index_Listar_Produtos Model_list = Produto_Repository.GetProdutoByAll();
        ViewModel.Index_List_Produto = Model_list.Index_List_Produto;
        return View("Index", ViewModel);
    }
}

其中“Produto_Repository.GetProdutoByAll();”再次返回“产品”列表。

如果我在表单中提供日期,则代码可以正常工作。日期采用“pt-BR”格式:23/03/2013。

但如果我在字段中不提供任何内容(我的视图中的两个日期字段),则“if(!ModelState.IsValid)”返回 true 并输入“if”,因为“CadastroInicialData”和“CadastroFinalData”都带有空值

期望的行为是 ViewModel 可以接受由“Nullable”或“DateTime?”授予的 null 或空值。

我尝试将值插入可空日期字段,执行以下操作:

if (ViewModel.CadastroInicialData == null)
    ViewModel.CadastroInicialData = Convert.ToDateTime("01/01/2013");
if (ViewModel.CadastroFinalData == null)
    ViewModel.CadastroFinalData = Convert.ToDateTime("01/01/2013");

但现在 ViewModel 返回以下错误: “是无效的日期格式”

一个注意事项是,我正在使用以下“解决方案”来为以下问题转换 pt-BR 日期格式的日期时间: Format datetime in asp.net mvc 4

当文本字段未填充日期时,如何使 ViewModel 接受空值? 我在这里有点困惑。我感谢任何帮助!谢谢!

【问题讨论】:

  • 这是您的数据注释,请看我的回复了解原因。
  • 嗨@Tommy,数据注释的助手是“GreaterThanOrEqualTo”而不是“GreaterThan”。如果日期时间都为空,则验证成功。
  • ...你是 100% 的吗?您的模型状态验证有什么错误?
  • 我相信问题来自“ApplyFormatInEditMode = true”。我发布一个答案只是让你解决这个问题。如果您真的想修复它,请查看此链接,它可能会对您有所帮助。 stackoverflow.com/questions/13253964/…

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


【解决方案1】:

您可以向模型类添加其他属性,然后使用它们来确定值是否为空。还要在您的视图中实现它们。见以下代码:

型号

public class Index_Listar_Produtos
{
    public List<Listar_Produto> Index_List_Produto { get; set; }

    [Display(Name = "Data de Cadastro Inicial")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
    public Nullable<DateTime> CadastroInicialData { get; set; }

    [Display(Name = "Data de Cadastro Final")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
    [GreaterThanOrEqualTo("CadastroInicialData", ErrorMessage = "\"Data Inicial\", deve ser maior que \"Data Final\"")]
    public Nullable<DateTime> CadastroFinalData { get; set; }


    public string GetStringTypeCadastroInicialData
    {
        get { return CadastroInicialData != null ? CadastroInicialData.Value.ToShortDateString() : DateTime.MinValue.ToShortDateString()(Or empty string ); }
    }

    public string GetStringTypeCadastroFinalData
    {
        get { return CadastroInicialData != null ? CadastroFinalData.Value.ToShortDateString() : DateTime.Now.ToShortDateString(); }
    }

}

查看

<td>
    @Html.LabelFor(Model => Model.GetStringTypeCadastroInicialData)<br />
    @Html.TextBoxFor(Model => Model.GetStringTypeCadastroInicialData)
    @Html.ValidationMessageFor(Model => Model.GetStringTypeCadastroInicialData)
</td>
<td>
    @Html.LabelFor(Model => Model.GetStringTypeCadastroFinalData)<br />
    @Html.TextBoxFor(Model => Model.GetStringTypeCadastroFinalData)
    @Html.ValidationMessageFor(Model => Model.GetStringTypeCadastroFinalData)
</td>

【讨论】:

  • 林,谢谢你的回答。你的代码几乎拯救了我的一天,唯一的“错误”是当我进入页面时 TextBoxFor 被“设置”为默认值(因为那时该值是 null )。文本框是搜索间隔的输入,不能开始填充。只有在控制器中,如果可以转换空值,那就太棒了。
  • @MarcosSantini,我认为如果值是空的时候你可以使用 "" 而不是使用 ""01/01/2013"。你也不需要使用 "{0: dd/MM/yyyy}" TextBoxFor 中的日期时间格式化程序。让我更新一下。
  • 林,刚刚注意到这是错误的。 "get { return CadastroInicialData != null ? CadastroFinalData.Value.ToShortDateString() : ""; }" 永远不会被触及。因为视图将尝试设置“GetStringTypeCadastroInicialData”,并且用户尝试搜索任何内容时都不会更改 CadastroFinalData! =(
  • @MarcosSantini,我不太清楚你的情况。但从你所说的来看,看起来你不能对 CadastroInicialData 和 CadastroFinalData 使用空字符串。您需要为两者或仅为 CadastroFinalData 传递适当的日期时间。我再次更新了我的帖子,试试看。
【解决方案2】:

代替

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

试试

public DateTime? CadastroInicialData { get; set; }

然后看它是否有值,你可以这样做:

if (CadastroInicialData.HasValue)
{
    // do your processing here
}

【讨论】:

  • 这根本没有帮助!约会时间?等于 Nullable,我使用了这两种 sintax,没有任何进步。这并不能解决我在 Controller 中通过 ModelView 传递可空日期的问题。 =P
【解决方案3】:

由于第二个可为空的 DateTime 值上的 GreaterThan 数据注释,您的模型状态失败。 null 不大于 null,因此失败。您将需要修改 GreaterThan 数据注释以不比较值是否为空,或者删除该数据注释并自己进行比较。一个例子可能是:

if(model.CadastroInicialData.HasValue() && model.CadastroFinalData.HasValue() && model.CadastroInicialData.Value > model.CadastroFinalData.Value){
    ModelState.AddModelError("CadastroInicialData", "CadastroInicialData must be less than CadastroFinalData");
}

if(!modelState.IsValid()){
   Produto_Repository.Index_Listar_Produtos Model_list = Produto_Repository.GetProdutoByAll();
   ViewModel.Index_List_Produto = Model_list.Index_List_Produto;
   return View("Index", ViewModel);
}

【讨论】:

    【解决方案4】:

    使用 DateTime.TryParseExact 代替使用 Convert.ToDateTime,您可以指定格式和区域性。下面的代码应该可以工作并修复错误:

    if (ViewModel.CadastroInicialData == null)
        ViewModel.CadastroInicialData = DateTime.TryParseExact(text, "MM/dd/yyyy",
                               CultureInfo.InvariantCulture,
                               DateTimeStyles.None,
                               out "01/01/2013");
    if (ViewModel.CadastroFinalData == null)
        ViewModel.CadastroFinalData = DateTime.TryParseExact(text, "MM/dd/yyyy",
                               CultureInfo.InvariantCulture,
                               DateTimeStyles.None,
                               out "01/01/2013");
    

    【讨论】:

    • 当我使用 DateTime.TryParseExact 时,它无法正常工作。返回值是布尔值,而不是预期的字符串值。无论如何,我真正需要的是能够将带有空值的“if (!ModelState.IsValid)”传递给日期。我试图手动“设置”这些值,因为我无法让 ModelView 传递“ModelState.isValid”。我真的认为这与我在以下链接stackoverflow.com/questions/11272851/… 中所做的“修复”有关。这可能是从 ModelView 和视图的 pt-BR 到 en-US 的日期格式转换错误。
    猜你喜欢
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 2012-12-14
    • 1970-01-01
    • 1970-01-01
    • 2020-06-18
    • 2023-04-11
    相关资源
    最近更新 更多