我正在尝试将MVC用于一个新项目之后,我已经使用了所有的示例和教程等.但是,我很难弄清楚某些事情应该发生在哪里.
例如,我有一个名为Profile的实体.此实体包含常规配置文件类型的东西以及DateTime类型的DateOfBirth属性.在HTML表单上,出生日期字段分为3个字段.现在,我知道我可以使用自定义模型绑定器来处理这个问题,但如果输入的日期不是有效日期怎么办?我应该在模型装订器中检查它吗?我的所有验证都应该放在模型装订器中吗?是否可以在模型绑定器中仅验证一些内容并在控制器或模型本身中验证其余内容?
这是我现在的代码,但它看起来不对我.看起来很脏或很臭.
namespace WebSite.Models { public class ProfileModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { DateTime birthDate; var form = controllerContext.HttpContext.Request.Form; var state = controllerContext.Controller.ViewData.ModelState; var profile = new Profile(); profile.FirstName = form["FirstName"]; profile.LastName = form["LastName"]; profile.Address = form["Address"]; profile.Address2 = form["Address2"]; profile.City = form["City"]; profile.State = form["State"]; profile.Zip = form["Zip"]; profile.Phone = form["Phone"]; profile.Email = form["Email"]; profile.Created = DateTime.UtcNow; profile.IpAddress = controllerContext.HttpContext.Request.UserHostAddress; var dateTemp = string.Format("{0}/{1}/{2}", form["BirthMonth"], form["BirthDay"], form["BirthYear"]); if (string.IsNullOrEmpty(dateTemp)) state.AddModelError("BirthDate", "Required"); else if (!DateTime.TryParse(dateTemp, out birthDate)) state.AddModelError("BirthDate", "Invalid"); else profile.BirthDate = birthDate; return profile; } } }
基于上面的示例代码,您将如何为3部分字段执行验证消息?在上面的例子中,我使用的是一个完全独立的键,它实际上并不对应于表单中的字段,因为我不希望在所有3个字段旁边显示错误消息.我只希望它出现在Year字段的右侧.
我认为在模型绑定器中进行验证是合理的.正如Craig指出的那样,验证主要是您的业务领域的属性,但是:
有时您的模型只是一个愚蠢的表示模型,而不是业务对象
您可以使用各种机制将验证知识表示到模型绑定器中.
托马斯给你一个#1的例子.
#2的一个示例是当您使用属性(如DataAnnotation属性[Required])声明性地描述验证知识时,或者将一些业务层验证服务注入自定义模型绑定器.在这些情况下,模型装订器是处理验证的理想场所.
话虽这么说,模型绑定(查找,转换和混洗数据到对象)和验证(数据符合我们的规范)是两个单独的问题.你可以说他们应该是单独的阶段/组件/可扩展性点,但我们拥有我们拥有的东西,尽管DefaultModelBinder在这两个职责之间做了一些区分.如果您要做的只是为特定类型的对象提供一些验证,您可以从DefaultModelBinder派生并覆盖用于属性级别验证的OnPropertyValidating方法,或者如果您需要整体视图,则覆盖OnModelUpdated.
这是我现在的代码,但它看起来不对我.看起来很脏或很臭.
对于您的特定代码,我会尝试仅为DateTime编写模型绑定器.默认模型绑定器可以处理绑定firstname,lastname等,并在它到达Profile上的DateTime属性时委托给自定义模型绑定器.另外,尝试在bindingContext中使用valueProvider而不是直接转到表单.这些东西可以给你更多的灵活性.
更多想法:ASP.NET MVC模型绑定的6个技巧.