隐藏

mvc3 用ModelState.IsValid进行 表单验证问题

发布:2014/11/10 21:06:51作者:管理员 来源:本站 浏览次数:1721

本人采用NHibernate 进行MVC3开发练习,有以下两类:
(大类:FirstAssetsClass,小类:SecondAssetsClass 一个大类可以包含多个小类)

public class FirstAssetsClass { [DisplayName("大类")] [Required(ErrorMessage = "请选择一个大类")] public virtual Guid FirstAssetsClassID { get; set; } [StringLength(50,MinimumLength=1, ErrorMessage = "{0}必须在{2}至{1}个字符之间")] [DisplayName("大类名称")] [Required] public virtual string FirstAssetsClassName{ get; set; } }
public class SecondAssetsClass { [DisplayName("小类 ")] [Required(ErrorMessage="请选择一个小类")] public virtual Guid SecondAssetsClassID { get; set; } [StringLength(50,MinimumLength =0, ErrorMessage = "{0}必须在{2}至{1}个字符之间")] [Required] [DisplayName("小类名称")] public virtual string SecondAssetsClassName { get; set; } //此句用于表示表间的NHibernate多对一关系统映射 public virtual FirstAssetsClass FirstAssetsClass { get; set; } }

NHibernate映射文件如下:

<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.MvcPowerTeamManage"> <class name ="NHibernate.MvcPowerTeamManage.Common.Assets.FirstAssetsClass,NHibernate.MvcPowerTeamManage" table ="firstAssetsClass"> <id name="FirstAssetsClassID" column="firstAssetsClassID" type="System.Guid"> <generator class="guid.comb"></generator> </id> <property name="FirstAssetsClassName" column="firstAssetsClassName" type="System.String"></property> </class> </hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly ="NHibernate.MvcPowerTeamManage"> <class name ="NHibernate.MvcPowerTeamManage.Common.Assets.SecondAssetsClass,NHibernate.MvcPowerTeamManage" table ="secondAssetsClass"> <id name="SecondAssetsClassID" column="secondAssetsClassID" type="System.Guid"> <generator class="guid.comb"></generator> </id> <property name="SecondAssetsClassName" column="secondAssetsClassName" type="System.String"></property> <many-to-one name="FirstAssetsClass" column="firstAssetsClassID" class="NHibernate.MvcPowerTeamManage.Common.Assets.FirstAssetsClass" ></many-to-one> </class > </hibernate-mapping>

以下为增加小类时的网页文件:

@model .MvcPowerTeamManage.Common.Assets.SecondAssetsClass @{ ViewBag.Title = "增加小类"; Layout = "~/Views/Shared/_LayOut_ChildMenu.cshtml"; } <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @using (Html.BeginForm()) { @Html.ValidationSummary(true) <fieldset> <legend>SecondAssetsClass</legend>
            @Html.HiddenFor(m=>m.FirstAssetsClass.FirstAssetsClassID)
        <div class="editor-label">
            @Html.LabelFor(model => model.SecondAssetsClassName)
        </div> <div class="editor-field"> @Html.EditorFor(model => model.SecondAssetsClassName) @Html.ValidationMessageFor(model => model.SecondAssetsClassName) </div>
        <p>
            <input type="submit" value="Create" /> </p>
    </fieldset> }

表单提交后的Controler中的代码:

public ActionResult AddSecondClass(SecondAssetsClass NewSecondAssetsClass) //public ActionResult AddSecondClass(string  NewSecondAssetsClass,Guid firstAssetsClassID) { if (ModelState.IsValid) { SecondAssetsClass _SecondAssetsClass=new SecondAssetsClass(); _SecondAssetsClass.Add(NewSecondAssetsClass); GetSecondAssetsClasses(NewSecondAssetsClass.FirstAssetsClass.FirstAssetsClassID);//刷新Json数据 return RedirectToAction("ClassEdit"); } else { return View(NewSecondAssetsClass); } }

问题是这样:提交后,ModelState.IsValid总是为“false”,因为ModelState中包含有对 NewSecondAssetsClass.FirstAssetsClass.FirstAssetsClassName的验证,因为表单中没有提交此 值。所以总是为“假”。当然SecondAssetsClass类可以改成如下:

					

public class SecondAssetsClass { [DisplayName("小类 ")] [Required(ErrorMessage="请选择一个小类")] public virtual Guid SecondAssetsClassID { get; set; } [StringLength(50,MinimumLength =0, ErrorMessage = "{0}必须在{2}至{1}个字符之间")] [Required] [DisplayName("小类名称")] public virtual string SecondAssetsClassName { get; set; }

public virtual Guid FirstAssetsClassID { get; set; } }

但这样似乎又失去使用NHibernat的便捷性,每次都要通过FirstAssetsClassID查询一次FirstAssetsClassName,请问有没有方法在不改变当前数据结构的情况下,只对ModelState.IsValid中的各值进行处理来实现。

当然可在Controler中,对 if (ModelState.IsValid)这句进行更改,采用逐项判断ModelState需要判断的内容,可以实现。但如表单内容项较多时较麻烦。

不知有无更好的解决?谢谢!


其实mvc 可以去除不必要的验证字段的

可以  [Bind(Include="name")] 就包括一个字段 或者[Bind(Exclude="name")] 排除一个字段

当然也可以直接移除          ModelState.Remove("name"),具体代码如下

 [HttpPost] [Bind(Include = "name")] public JsonResult FileUpload(string id) { ModelState.Remove("name"); UploadContext upload = UploadContextFactory.GetUploadContext(id); if ((upload != null) && (upload.Status == UploadStatus.Complete)) { upload.SaveFile("filepath", Request.MapPath("~/uploadfiles/")); } return Json(new { result = Convert.ToInt16(100) }); }


认真的活,认真的爱!

因为我用NHibernate作为数据据映射,所以在类中存在以下表示关系的字段(类型为类)

 //此句用于表示表间的NHibernate多对一关系统映射
       
public virtual FirstAssetsClass  FirstAssetsClass { get; set; }
FirstAssetsClass类中存的FirstAssetsClassID字段需要进行验证。如采用[Bind(Exclude="XXX")] 排除一个字段,则只能排除小类中的FirstAssetsClass 字段,而不能排除FirstAssetsClassName字段。

当然你的方法在一般情况下可用,谢谢指导!

已解决:用以下两种方法都可加以解决

方法一:在新建时把原Action

 public ActionResult AddSecondClass(Guid id) { Guid firstAssetsClassID = id; SecondAssetsClass NewSecondAssetsClass = new SecondAssetsClass(); NewSecondAssetsClass.FirstAssetsClass = new FirstAssetsClass(); NewSecondAssetsClass.FirstAssetsClass.FirstAssetsClassID = firstAssetsClassID; return View(NewSecondAssetsClass); }

更改为以下:

 public ActionResult AddSecondClass(Guid id) { Guid firstAssetsClassID = id; SecondAssetsClass NewSecondAssetsClass = new SecondAssetsClass(); NewSecondAssetsClass.FirstAssetsClass = new FirstAssetsClass(); NewSecondAssetsClass.FirstAssetsClass.FirstAssetsClassID = firstAssetsClassID; //新增以下初始设置,值可任意设置,因它是不会加入数据库中的,只要满足类中的对应字段要求即可 NewSecondAssetsClass.FirstAssetsClass.FirstAssetsClassName = "newFirstClassName"; return View(NewSecondAssetsClass); }

再在表单中新加对应的隐藏域:

@model NHibernate.MvcPowerTeamManage.Common.Assets.SecondAssetsClass @{ ViewBag.Title = "增加小类"; Layout = "~/Views/Shared/_LayOut_ChildMenu.cshtml"; } <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @using (Html.BeginForm()) { @Html.ValidationSummary(true) <fieldset> <legend>SecondAssetsClass</legend>
    @Html.HiddenFor(m=>m.FirstAssetsClass.FirstAssetsClassID) 
    @---*新增的隐藏域---*@
    @Html.HiddenFor(m=>m.FirstAssetsClass.FirstAssetsClassName)      
    @*--------------*@
        <div class="editor-label">
            @Html.LabelFor(model => model.SecondAssetsClassName)
        </div> <div class="editor-field"> @Html.EditorFor(model => model.SecondAssetsClassName) @Html.ValidationMessageFor(model => model.SecondAssetsClassName) </div>
        <p>
            <input type="submit" value="Create" /> </p>
    </fieldset> } <div> @Html.ActionLink("Back to List", "Index") </div>

那么就能在Action 直接使用ModelState.IsValid进行验证;

方法二:

 public ActionResult AddSecondClass(Guid id) { Guid firstAssetsClassID = id; SecondAssetsClass NewSecondAssetsClass = new SecondAssetsClass(); NewSecondAssetsClass.FirstAssetsClass = new FirstAssetsClass(); NewSecondAssetsClass.FirstAssetsClass.FirstAssetsClassID = firstAssetsClassID; //不增加以下句-------- //NewSecondAssetsClass.FirstAssetsClass.FirstAssetsClassName = "newFirstAssetsClassName"; //-------------------------------------- return View(NewSecondAssetsClass); }

提交页面如下:

@model NHibernate.MvcPowerTeamManage.Common.Assets.SecondAssetsClass @{ ViewBag.Title = "增加小类"; Layout = "~/Views/Shared/_LayOut_ChildMenu.cshtml"; } <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @using (Html.BeginForm()) { @Html.ValidationSummary(true) <fieldset> <legend>SecondAssetsClass</legend>
    @Html.HiddenFor(m=>m.FirstAssetsClass.FirstAssetsClassID) 
    @*---不增以下隐藏域---*@
    @*@Html.HiddenFor(m=>m.FirstAssetsClass.FirstAssetsClassName)*@      
    @*--------------*@
        <div class="editor-label">
            @Html.LabelFor(model => model.SecondAssetsClassName)
        </div> <div class="editor-field"> @Html.EditorFor(model => model.SecondAssetsClassName) @Html.ValidationMessageFor(model => model.SecondAssetsClassName) </div>
        <p>
            <input type="submit" value="Create" /> </p>
    </fieldset> } <div> @Html.ActionLink("Back to List", "Index") </div>

更改提交后的验证,去除不必要的字段

 [HttpPost] public ActionResult AddSecondClass(SecondAssetsClass NewSecondAssetsClass) { if (ModelState["FirstAssetsClass.FirstAssetsClassID"].Errors.Count == 0 & ModelState["SecondAssetsClassName"].Errors.Count == 0) //if(ModelState.IsValid) { SecondAssetsClass _SecondAssetsClass = new SecondAssetsClass(); _SecondAssetsClass.Add(NewSecondAssetsClass); GetSecondAssetsClasses(NewSecondAssetsClass.FirstAssetsClass.FirstAssetsClassID);//刷新Json数据 return RedirectToAction("ClassEdit"); } else { return View(NewSecondAssetsClass); } }
即可完成数据的验证。


其实mvc 可以去除不必要的验证字段的

可以  [Bind(Include="name")] 就包括一个字段 或者[Bind(Exclude="name")] 排除一个字段

当然也可以直接移除          ModelState.Remove("name"),具体代码如下

 [HttpPost] [Bind(Include = "name")] public JsonResult FileUpload(string id) { ModelState.Remove("name"); UploadContext upload = UploadContextFactory.GetUploadContext(id); if ((upload != null) && (upload.Status == UploadStatus.Complete)) { upload.SaveFile("filepath", Request.MapPath("~/uploadfiles/")); } return Json(new { result = Convert.ToInt16(100) }); }


认真的活,认真的爱!

因为我用NHibernate作为数据据映射,所以在类中存在以下表示关系的字段(类型为类)

 //此句用于表示表间的NHibernate多对一关系统映射
       
public virtual FirstAssetsClass  FirstAssetsClass { get; set; }
FirstAssetsClass类中存的FirstAssetsClassID字段需要进行验证。如采用[Bind(Exclude="XXX")] 排除一个字段,则只能排除小类中的FirstAssetsClass 字段,而不能排除FirstAssetsClassName字段。

当然你的方法在一般情况下可用,谢谢指导!