MVC3学习第七章 排山倒海第三变----利用MVC3实现数据验证以及完成用户数据的编辑

本章学习内容

1.用DataAnnotations实现模型验证

2.实现用户数据的编辑实现(ActionResult.ViewResult)

1.用DataAnnotations实现模型验证

上一章中我们已经完成了用的添加和列表操作,对于一个完整的增删改查来说我们还缺少编辑和删除,这在本章后续会完成。我们先来回顾一下前文的添加,输入数据,入库保存,很简单的操作,有没有发现有什么不足的地方?或许聪明的你已经发现了,我们虽然保存了用户信息,但明显信息验证不够健壮,甚至连最起码的是否必须输入都没有验证,或许你想到了这时候可以去页面写验证的js,又或者你觉得此时缺少了webform下的RequiredFieldValidator和CustomValidator使得mvc的验证不太方便,其实,mvc的验证远比这些验证方式更加灵活好用,接下来我们就为我们的UserInfo加入表单验证。

首先,罗列一下我们要达到的验证效果:

1).所有数据必须输入,除了邮箱以外;

2).密码应是3-8个字符

3).邮箱和电话的格式应该正确

先就这么多吧,没有用到的验证我们之后也会讲到,打开Models/UserInfo,修改完整代码如下:

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

namespace MyShopTest.Models
{
    public class UserInfo
    {
        [ScaffoldColumn(false)]
        public int Id { get; set; }
        [Display(Name="用户名")]
        [Required(ErrorMessage="必须输入用户名!")]
        public string UserName { get; set; }
        [Display(Name = "密码")]
        [Required(ErrorMessage = "必须输入密码!")]
        [StringLength(8, MinimumLength = 3, ErrorMessage = "密码长度必须是3到8个字符之间")]
        public string UserPwd { get; set; }
        [Display(Name = "电话")]
        [Required(ErrorMessage = "必须输入电话!")]
        [RegularExpression(@"((\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$)",ErrorMessage="电话格式不正确")]
        public string Phone { get; set; }
        [Display(Name = "邮箱")]
        [RegularExpression(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "邮箱格式不正确")]
        public string Email { get; set; }
        private DateTime addTime;
        [Display(Name="注册时间")]
        [Required()]
        public DateTime AddTime
        {
            get
            {
                if (addTime == null)
                {
                    return DateTime.Now;
                }
                return addTime;
            }
            set { addTime = value; }
        }
    }
}

我们来解释一下这些属性头部的验证代码:

  • Required 必须 – 表示这个属性是必须提供内容的字段
  • Display 显示名 – 定义表单字段的提示名称(也可以写成DisplayName("要显示的名字"))
  • StringLength 字符串长度 – 定义字符串类型的属性的最大长度
  • Range 范围 – 为数字类型的属性提供最大值和最小值,此处没有用到
  • Bind 绑定 – 列出在将请求参数绑定到模型的时候,包含和不包含的字段,此处没有用到,一般写在实体某些类名的头部,格式如[Bind(Exclude = "OrderId")]
  • ScaffoldColumn 支架列 - 在编辑表单的时候,需要隐藏起来的的字符,主键会自动隐藏,这里可以不用为Id写,此处只是为了理解
  • RegularExpression,自定义正则验证

 重新编译项目,修改我们的Create视图,以便应用这些验证,修改UserInfo/Create.cshtml,完整代码如下:

@model MyShopTest.Models.UserInfo
@{
    ViewBag.Title = "添加用户";
}
<h2>
    添加用户</h2>
<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())
{
    <fieldset>
        <legend>添加用户</legend>
         <div class="editor-label">
            @Html.LabelFor(model => model.UserName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.UserName)
            @Html.ValidationMessageFor(model => model.UserName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.UserPwd)
        </div>
        <div class="editor-field">
            @Html.PasswordFor(model => model.UserPwd)
            @Html.ValidationMessageFor(model => model.UserPwd)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Phone)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Phone)
            @Html.ValidationMessageFor(model => model.Phone)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Email)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Email)
            @Html.ValidationMessageFor(model => model.Email)
            <input type="hidden" name="AddTime" value="@DateTime.Now"/>
        </div>
        <p>
            <input type="submit" value="添加" />
        </p>
    </fieldset>
}
<div>
    <a href="Index">返回列表</a>
</div>

我们来解释一下这个修改后的Create视图我们不认识的标签,

@Html.LabelFor(model => model.UserName)等类似的代码

之前我们直接写的是“用户名”,“密码”等文字,现在换成了这一段代码, 它的意思是使用model.UserName的Display信息显示在此处,再看看我们的UserName属性的代码

        [Display(Name="用户名")]
        [Required(ErrorMessage="必须输入用户名!")]
        public string UserName { get; set; }

此时使用@Html.LabelFor(model => model.UserName)就会显示用户名

再来看下一段代码:

@Html.EditorFor(model => model.UserName)

如同上一个的解释,不过此处的意思是输出一个model.UserName的文本框,之前我们是手写的文本框,此处也罗列一下:

<input type="text" name="UserName" />

两者实现的功能基本一样,之所以说基本,是因为还有不一样的,原因是使用@Html.EditorFor配合紧接着要说的代码段,可以实现自动验证

 @Html.ValidationMessageFor(model => model.UserPwd)

这段代码就是执行我们的那些验证规则并且输出验证信息了,请注意此时只有使用@Html.EditFor或者其他@Html.输出的html标签,才能搭配输出验证信息,如果是我们自己手写的文本框则不可以。

好了,我们已经编写好了验证规则,我们来看一下效果,重新编译项目,在首页点击用户管理

报错了,恭喜你,修改差不多成功了。为什么会报错呢?因为我们修改了实体规则,这和数据库里现有的字段规则不符,所以报错了,要解决这个错误我们有两种方法,一是手动修改数据库字段的规则和实体一致,二是重新根据此实体来创建数据库。为了简便测试,我们直接删除掉数据库里现有的MyShop数据库,让系统重新创建,当然如果有很多数据时我们进行此操作很明显很危险,不过目前只是测试,所以不用考虑。

重新运行程序,进入用户管理

点击添加用户,输入一些错误信息,点击添加,看一下验证效果:

我们期望的验证已经基本都达到了,添加符合验证的信息,点击添加

 

操作成功。

2.实现用户数据的编辑实现

现在我们来实现用户的修改功能

还是一一样,我们先来创建对应的用户修改的Action,修改UserInfoController.cs的完整代码如下:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MyShopTest.Models;
using System.Data;
namespace MyShopTest.Controllers
{
    public class UserInfoController : Controller
    {
        //数据访问
        private MyShopDataEntities db = new MyShopDataEntities();
        /// <summary>
        /// 用户列表Action
        /// </summary>
        /// <returns></returns>
        public ActionResult Index()
        {
            var users = db.UserInfos.ToList();
            return View(users);
        }
        /// <summary>
        /// 添加用户页面展示
        /// </summary>
        /// <returns></returns>
        public ActionResult Create()
        {
            return View();
        }
        /// <summary>
        /// 添加用户处理
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Create(UserInfo user)
        {
            db.UserInfos.Add(user);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        /// <summary>
        /// 编辑用户页面展示
        /// </summary>
        /// <returns></returns>
        public ActionResult Edit(int id)
        {
            var user = db.UserInfos.Find(id);
            return View(user);
        }
        /// <summary>
        /// 编辑用户处理
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Edit(UserInfo user)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    db.Entry(user).State = EntityState.Modified;
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
                else
                {
                    throw new Exception();
                }
            }
            catch (Exception)
            {

                ModelState.AddModelError("", "更改失败");
            }

            return View(user);
        }

    }
}

 

我们来解析一下新增Edit代码的新知识,db.UserInfos.Find(id)查找某个Id的用户,之后返回给视图,作用是在视图页面赋值;

ModelState.IsValid是用来验证当前模型实例是否有效的,说的更通俗一点,就是是否通过了字段合法性检查的验证,通过了则返回true,否则返回false;db.Entry(user).State = EntityState.Modified;意思是表名当前对象已经更新,但是还没保存,db.SaveChanges();执行数据库更改,如果一切操作顺利,则返回列表页,如果没有通过验证,我们来抛出一个异常,如果期间更新出错,也进入异常处理,异常处理里ModelState.AddModelError("", "更改失败");就是为当前模型添加错误信息,除了异常则将当前模型返回此Action对应的视图,视图里如果有 @Html.ValidationSummary(true)语句,则会输出错误信息,这在稍后的修改视图里大家就可以看到。

现在添加Edit视图,修改完整代码如下

@model MyShopTest.Models.UserInfo

@{
    ViewBag.Title = "用户编辑";
}

<h2>用户编辑</h2>

<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>用户编辑</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.UserName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.UserName)
            @Html.ValidationMessageFor(model => model.UserName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.UserPwd)
        </div>
        <div class="editor-field">
            @Html.PasswordFor(model => model.UserPwd)
            @Html.ValidationMessageFor(model => model.UserPwd)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Phone)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Phone)
            @Html.ValidationMessageFor(model => model.Phone)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Email)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Email)
            @Html.ValidationMessageFor(model => model.Email)
        </div>

        <p>
            <input type="submit" value="修改" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("返回列表", "Index")
</div>

 代码应该都说过了,没有新知识, @Html.ValidationSummary(true)是用来显示Model错误信息的。

除了@Html.ActionLink,在此也解释一下,@Html.ActionLink是用来创建链接的,它也有很多重载的方法,简单说明几个:

一 Html.ActionLink("linkText","actionName")
该重载的第一个参数是该链接要显示的文字,第二个参数是对应的控制器的方法,
默认控制器为当前页面的控制器,如果当前页面的控制器为Products,则 Html.ActionLink("detail","Detail")
则会生成 <a href="/Products/Detail">all</a>

二 Html.ActionLink("linkText","actionName","controlName")
该重载比第一个重载多了一个参数,他指定了控制器的名称,
如Html.ActionLink("detail","Detail","Products")则会生成
<a href="Products/Detail">all</a>

三 Html.ActionLik("linkText","actionName",routeValues)
routeValue可以向action传递参数,如Html.ActionLink("detail","Detail",new { id=1})
会生成 <a href="Products/Detail/1">detail</a>,
此处假设当前的控制器是Products.

详细请参考http://blog.csdn.net/jingmeifeng/article/details/7792151

现在我们在列表页加上编辑链接,修改Index.cshtml完整代码如下:

@model IEnumerable<MyShopTest.Models.UserInfo>
@{
    ViewBag.Title = "用户列表";
}
<h2>
    用户列表</h2>
<p>
    <a href="/UserInfo/Create">添加用户</a>
</p>
<table>
    <tr>
        <th>
            用户名
        </th>
        <th>
            电话
        </th>
        <th>
            邮箱
        </th>
        <th>
            注册时间
        </th>
        <th>
            操作
        </th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>
                @item.UserName
            </td>
            <td>
                @item.Phone
            </td>
            <td>
                @item.Email
            </td>
            <td>
                @item.AddTime
            </td>
            <td>
                @Html.ActionLink("编辑", "Edit", new { id=item.Id})
            </td>
        </tr>
    }
</table>

重新运行项目,用户管理,点击编辑,

结果如下:

修改任意数据,点击修改:

 

 提示错误信息,错误原因是更新时获取不到Id,我们的编辑页面还缺少一个保存当前修改信息的Id的隐藏域。加入下面的隐藏域代码到Edit.cshtml,修改后的完整代码是:

@model MyShopTest.Models.UserInfo

@{
    ViewBag.Title = "用户编辑";
}

<h2>用户编辑</h2>

<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>用户编辑</legend>

        @Html.HiddenFor(model => model.Id)

        <div class="editor-label">
            @Html.LabelFor(model => model.UserName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.UserName)
            @Html.ValidationMessageFor(model => model.UserName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.UserPwd)
        </div>
        <div class="editor-field">
            @Html.PasswordFor(model => model.UserPwd)
            @Html.ValidationMessageFor(model => model.UserPwd)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Phone)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Phone)
            @Html.ValidationMessageFor(model => model.Phone)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Email)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Email)
            @Html.ValidationMessageFor(model => model.Email)
            
        </div>
        @Html.HiddenFor(model => model.AddTime)
      

        <p>
            <input type="submit" value="修改" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("返回列表", "Index")
</div>

不用生成,直接刷新页面,重新修改数据提交

提交后结果

 用户编辑完成

 

 

posted @ 2013-06-23 21:49  韩若怅  阅读(677)  评论(4编辑  收藏  举报