[转]ASP.NET MVC 入门8、ModelState与数据验证

ViewData有一个ModelState的属性,这是一个类型为ModelStateDictionary的ModelState类型的字典集合。在进行数据验证的时候这个属性是比较有用的。在使用Html.ValidationMessage()的时候,就是从ViewData.ModelState中检测是否有指定的KEY,如果存在,就提示错误信息。例如在前一篇文章ASP.NET MVC 入门7、Hellper与数据的提交与绑定中使用到的UpdateModel方法:

我们在View中使用Html.ValidationMessage(string modelName)来对指定的属性进行验证:

Html.ValidationMessage()有几个重载:

其中ValidationSummary()是用于显示全部的验证信息的。跟ASP.NET里面的ValidationSummary验证控件差不多。

我们测试一下/Admin/Setting页面:

在用UpdateModel方法更新BlogSettings.Instance.PostsPerPage的时候,当我们如图所示填写"10d"的时候,由于PostsPerPage为整型的,所以UpdateModel方法就会出错,同时会往ViewData.ModelState添加相应的错误信息,从而Html.ValidationMessage()方法就可以从ViewData.ModelState中检测到错误并提示。同时Html.ValidationMessage()方法会为出错的属性的输入框添加一个名为"input-validation-error"的CSS类,同时后面的提示信息的CSS类名为"field-validation-error":

CSS类的样式是可以由我们自己自由定义的。如上图的红色高亮显示。

好,下面我们来实现发表新随笔的功能。我们先写一个提供用户输入随笔内容的表单页面:

<p>
    <label for="Title">标题</label>
    <%=Html.TextBox("Title", new { id = "Title", @class = "required" })%>
    <%=Html.ValidationMessage("Title")%>
</p>
<p>
    <label for="Content">内容</label>
    <%=Html.TextArea("Content")%>
    <%=Html.ValidationMessage("Content")%>
</p>
<p>
    <label for="Slug">URL地址别名(如果为空则和标题同名)</label>
    <%=Html.TextBox("Slug", new { id = "Slug", @class = "required" })%>
    <%=Html.ValidationMessage("Slug")%>
</p>

然后我们对用户提交过来的数据进行保存:

[AcceptVerbs("POST"), ActionName("NewPost")]
public ActionResult SaveNewPost(FormCollection form)
{
    Post post = new Post();

try
    {
        UpdateModel(post, new[] { "Title", "Content", "Slug" });
    }
    catch
    {
        return View(post);
    }

post.Save();
    return ShowMsg(new List<string>() { "发表新随笔成功" });
}

由于这三个值都是字符串类型,所以如果值为空的话,UpdateModel也是不会出错的,而我们的Title和Content是不允许为空的,或者我们想我们的Slug的长度不能超过100,也就是需要有我们自己的业务规则。这时候我们或许会这样写:

try
{
    UpdateModel(post, new[] { "Title", "Content", "Slug" });
}
catch
{
    return View(post);
}

if (string.IsNullOrEmpty(post.Title))
{
    ViewData.ModelState.AddModelError("Title", post.Title, "标题不能为空");
}
if (string.IsNullOrEmpty(post.Content))
{
    ViewData.ModelState.AddModelError("Content", post.Content, "内容不能为空");
}

if (!ViewData.ModelState.IsValid)
{
    return View(post);
}

ViewData.ModelState提供了一个AddModelError的方法,方便我们添加验证失败的信息。我们可以如上代码这样进行对象的业务规则验证,但是一旦业务规则多了,这样的代码是非常壮观的,而且不好控制。那么我们该怎么更好的进行业务规则的验证呢?得意于BlogEngine.Net的良好架构,我们可以很轻松的完成这一点。

首先,让我们修改一下BlogEngine.Core里面BusinessBase的代码。我们前面说过,BusinessBase实现了IDataErrorInfo接口,该接口有个索引器,导致ViewData.Eval()方法调用时搜索索引器的值时返回String.Empty而使ViewData.Eval()认为是找到值了,从而失效。

我们可以将return string.Empty修改为return null。但我们这里并不需要用到这个接口,所以我们把该接口去掉,并把相应的代码注释了。然后我们再暴露一个BrokenRules的属性,用于返回当前的所有破坏性业务规则(红框部分代码为我们添加的):

BusinessBase提供了一个抽象的ValidationRules方法,用于在业务类重写这个方法往里面添加验证规则(具体请看BusinessBase的Validation节)。

Validation

我们在Post类中重写这个方法来添加验证规则:

然后我们可以在Controller的Action中很优雅的书写我们的代码来进行业务规则的验证:

[AcceptVerbs("POST"), ActionName("NewPost")]
public ActionResult SaveNewPost(FormCollection form)
{
    Post post = new Post();

try
    {
        UpdateModel(post, new[] { "Title", "Content", "Slug" });
    }
    catch
    {
        return View(post);
    }

if (!post.IsValid)
    {
        foreach (string key in post.BrokenRules.Keys)
        {
            ViewData.ModelState.AddModelError(key, form[key], post.BrokenRules[key]);
        }
        return View(post);
    }

post.Save();
    return ShowMsg(new List<string>() { "发表新随笔成功" });
}

我们注意到上面的Action中用到了一个FormCollection 的参数,这个参数系统会自动将Form提交过来的全部表单值(Request.Form)赋给它的。客户端验证可以用jQuery的验证插件来,这里就不罗嗦了。

暂时就写这么多吧,想到什么再补充。Enjoy!Post by Q.Lee.lulu

本文的Blog程序示例代码: 4mvcBlog_8.rar

时间: 2024-10-07 15:32:36

[转]ASP.NET MVC 入门8、ModelState与数据验证的相关文章

ASP.NET MVC 入门8、ModelState与数据验证

数据验证包括服务器端验证和客户端的验证, 本文介绍的MVC数据库端的数据验证实现. 客户端的数制验证可以使用JQuery的验证插件来实现. Html.ValidationMessage()的时候,就是从ViewData.ModelState中检测是否有指定的KEY,如果存在,就提示错误信息. ValidationMessage(modelName) 指定控件的验证错误信息; ValidationSummary() 表单所有控件的验证错误信息. 验证未通过, 目标控件和验证错误信息HTML标签,都

[渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序更新相关数据

这是微软官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里是第六篇:为ASP.NET MVC应用程序更新相关数据 原文: Updating Related Data with the Entity Framework in an ASP.NET MVC Application 译文版权所有,谢绝全文转载--但您可以在您的网站上添加到该教程的链接. 在之前的教程中您已经成功显示了相关数据.在本教程中

ASP.NET MVC 入门系列教程

ASP.NET MVC 入门1.简介 ASP.NET MVC 入门2.项目的目录结构与核心的DLL ASP.NET MVC 入门3.Routing ASP.NET MVC 入门4.Controller与Action ASP.NET MVC 入门5.View与ViewData ASP.NET MVC 入门6.TempData ASP.NET MVC 入门7.Hellper与数据的提交与绑定 ASP.NET MVC 入门8.ModelState与数据验证 ASP.NET MVC 入门9.Action

[渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序读取相关数据

这是微软官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里是第六篇:为ASP.NET MVC应用程序读取相关数据 原文:Reading Related Data with the Entity Framework in an ASP.NET MVC Application 译文版权所有,谢绝全文转载--但您可以在您的网站上添加到该教程的链接. 在之前的教程中您已经完成了学校数据模型.在本教程中你将

26、ASP.NET MVC入门到精通——后台管理区域及分离、Js压缩、css、jquery扩展

本系列目录:ASP.NET MVC4入门到精通系列目录汇总 有好一段时间没更新博文了,最近在忙两件事:1.看书,学习中...2.为公司年会节目做准备,由于许久没有练习双截棍了,难免生疏,所以现在临时抱佛脚.深圳最近的天气反常,许多人感冒了,我也成为其中之一,大家注意身体... 这一篇,我来简单的讲一下接下来项目中会用到的一些杂七杂八的技术. 区域及分离 在15.ASP.NET MVC入门到精通——MVC-路由中,我已经简要说明了区域的分离. 1.右键单击Web项目,“添加”——“区域”,区域名,

Asp.net MVC入门视频教程

编程开发 > Asp.net视频教程 > Asp.net MVC入门视频教程 > 1.传统web处理方式和mvc处理方式 上传日期:2014-08-16 10:02:45  相关摘要:  - 怎么一创建传统补间就成了上下移动的了 - web 服务器 第一次进入站点速度慢是什么问题?? - EF中怎么处理像Sql多表连接的问题? 2.mvc项目会自动导入mvc程序集 上传日期:2014-08-16 10:14:51  相关摘要:  - Asp.net mvc 可以不用js吗 - 项目发布的

ASP.NET MVC 入门1、简介

什么是MVC模式 MVC(Model-View-Controller,模型—视图—控制器模式)用于表示一种软件架构模式.它把软件系统分为三个基本部分:模型(Model),视图(View)和控制器(Controller). 那么MVC模式和我们熟悉的WebForm模式有什么不同呢?他的各个部分又是怎样分工的呢? 我们先来看一下普通的WebForm模式下,我们请求一个例如http://www.51mvc.com/blog/index.aspx的URL,那么我们的WebForm程序会到网站根目录下去寻

ASP.NET MVC 入门4、Controller与Action

原帖地址:http://www.cnblogs.com/QLeelulu/archive/2008/10/04/1303672.html Controller是MVC中比较重要的一部分.几乎所有的业务逻辑都是在这里进行处理的,并且从Model中取出数据.在ASP.NET MVC Preview5中,将原来的Controller类一分为二,分为了Controller类和ControllerBase类.Controller类继承自ControllerBase类,而ControllerBase实现是了

ASP.NET MVC 入门2、项目的目录结构与核心的DLL

原帖地址:http://www.cnblogs.com/QLeelulu/archive/2008/10/03/1303521.html 我们新建一个ASP.NET MVC的Web Application后,默认的情况下,项目的目录结构如下: App_Data :这个目录跟我们一般的ASP.NET website是一样的,用于存放数据. Content :这个目录是建议用来存放一下资源文件的.例如CSS.JS.图片等等.当然你不愿意的话,完全可以不放到这里来. Controllers :这个目录