C#MVC 4 ViewModel不接受null DateTime
学习C#和mvc4在这里遇到了一些麻烦。
问题出现在我的应用程序的filter部分。 我有一个ViewModel,它抓取数据库的“Listar_Produtos”列表,以及一些搜索选项的字段。
我打算做的是让filter接受任何字段,即使它是空值。 因为我会根据这些参数制作filter。
我有一个Viewmodel:
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 Index_List_Produto { get; set; } [Display(Name = "Data de Cadastro Inicial")] [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")] public Nullable 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 CadastroFinalData { get; set; } } } }
我有以下观点:
@Html.LabelFor(Model => Model.CadastroInicialData)
@Html.TextBoxFor(Model => Model.CadastroInicialData, "{0:dd/MM/yyyy}") @Html.ValidationMessageFor(Model => Model.CadastroInicialData) @Html.LabelFor(Model => Model.CadastroFinalData)
@Html.TextBoxFor(Model => Model.CadastroFinalData, "{0:dd/MM/yyyy}") @Html.ValidationMessageFor(Model => Model.CadastroFinalData)
在我的控制器中,我有:
[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();” 再次返回“Produtos”列表。
如果我在表单中提供日期,代码工作正常。 日期为“pt-BR”格式:23/03/2013。
但是如果我在Fields中没有提供任何内容(在我的视图中都是Datefields),那么“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 dateformat的日期时间,问题如下: 在asp.net mvc 4中格式化日期时间
当文本字段没有填充日期时,如何使ViewModel接受空值? 我在这里有点困惑。 我赞成任何帮助! 谢谢 !
您可以向Model类添加其他属性,然后使用它们来确定值是否为null。 并在您的视图中实现它们。 见下面的代码:
模型
public class Index_Listar_Produtos { public List Index_List_Produto { get; set; } [Display(Name = "Data de Cadastro Inicial")] [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")] public Nullable 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 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(); } } }
视图
@Html.LabelFor(Model => Model.GetStringTypeCadastroInicialData)
@Html.TextBoxFor(Model => Model.GetStringTypeCadastroInicialData) @Html.ValidationMessageFor(Model => Model.GetStringTypeCadastroInicialData) @Html.LabelFor(Model => Model.GetStringTypeCadastroFinalData)
@Html.TextBoxFor(Model => Model.GetStringTypeCadastroFinalData) @Html.ValidationMessageFor(Model => Model.GetStringTypeCadastroFinalData)
代替
public Nullable CadastroInicialData { get; set; }
尝试
public DateTime? CadastroInicialData { get; set; }
然后要查看它是否有值,你可以这样做:
if (CadastroInicialData.HasValue) { // do your processing here }
由于第二个可以为空的DateTime值上的GreaterThan
数据注释,您的模型状态失败。 null不大于null,因此失败。 您将需要修改GreaterThan
数据注释,以便不比较值是否为null或删除该数据注释并自行进行比较。 一个例子可能是:
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); }
而不是使用Convert.ToDateTime使用DateTime.TryParseExact,您可以指定格式和文化。 以下代码应该工作并修复错误:
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");