65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET MVC 服务器端验证

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.96/5 (24投票s)

2014年1月14日

CPOL

3分钟阅读

viewsIcon

210568

downloadIcon

1713

本文解释了使用数据注释 API 进行 ASP.NET MVC 服务器端验证的基础知识。

引言

本文解释了使用数据注释 API 进行 ASP.NET MVC 服务器端验证的基础知识。ASP.NET MVC 框架会验证传递给正在执行的控制器操作的任何数据。它使用 ModelState 对象填充它发现的任何验证失败,并将该对象传递给控制器。然后,控制器操作可以查询 ModelState 以发现请求是否有效并相应地做出反应。

在本文中,我将使用两种方法来验证模型数据。一种是手动向 ModelState 对象添加错误,另一种是使用数据注释 API 来验证模型数据。

方法 1:手动向 ModelState 对象添加错误 

我在 Models 文件夹下创建了一个 User 类。User 类有两个属性 "Name" 和 "Email"。 "Name" 字段有必填字段验证,而 "Email" 字段有 Email 验证。 让我们看看实现验证的过程。 按照以下方式创建 User 模型

namespace ServerValidation.Models
 {
    public class User
    {
        public string Name { get; set; }
        public string Email { get; set; }       
    }
 } 

之后,我在 User 控制器(UserController.cs,在 Controllers 文件夹下)中创建了一个控制器操作。该操作方法包含对 NameEmail 字段的 Email 验证的必需验证逻辑。 我在 ModelState 上添加了一条带有键的错误消息,只要模型中的数据未通过验证,该消息就会显示在视图中。

using System.Text.RegularExpressions;
using System.Web.Mvc; 
namespace ServerValidation.Controllers
{
    public class UserController : Controller
    {       
        public ActionResult Index()
        {           
            return View();
        }
        [HttpPost]
        public ActionResult Index(ServerValidation.Models.User model)
        {
            if (string.IsNullOrEmpty(model.Name))
            {
                ModelState.AddModelError("Name", "Name is required");
            }
            if (!string.IsNullOrEmpty(model.Email))
            {
                string emailRegex = @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
                                         @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
                                            @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
                Regex re = new Regex(emailRegex);
                if (!re.IsMatch(model.Email))
                {
                    ModelState.AddModelError("Email", "Email is not valid");
                }
            }
            else
            {
                ModelState.AddModelError("Email", "Email is required");
            }
            if (ModelState.IsValid)
            {
                ViewBag.Name = model.Name;
                ViewBag.Email = model.Email;
            }
            return View(model);
        }
    }
} 

此后,我在 User 文件夹下创建了一个用于用户输入的视图 (Index.cshtml)。

@model ServerValidation.Models.User
@{
    ViewBag.Title = "Index";
} 
@using (Html.BeginForm()) {
    if (@ViewData.ModelState.IsValid)
    {
        if(@ViewBag.Name != null)
        {
            <b>
                Name : @ViewBag.Name<br />
                Email : @ViewBag.Email
            </b>
        }
    }     
    <fieldset>
        <legend>User</legend> 
        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name) 
            @if(!ViewData.ModelState.IsValid)
            {       
                <span class="field-validation-error">
                @ViewData.ModelState["Name"].Errors[0].ErrorMessage</span>
            }            
        </div> 
        <div class="editor-label">
            @Html.LabelFor(model => model.Email)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Email)
            @if (!ViewData.ModelState.IsValid)
            {       
                 <span class="field-validation-error">
                 @ViewData.ModelState["Email"].Errors[0].ErrorMessage</span>
            }         
        </div>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
} 

运行应用程序并以各种方式进行测试

我们将测试各种场景以测试验证。 让我们逐一查看每一个。 

  1. 当所有字段都为空时

    Validation Message when both fields are empty

    图 1.1:当两个字段都为空时的验证消息
     
  2. Name 字段为空,但 Email 无效时

    Validation Message when Email is not valid

    图 1.2:当 Email 无效时的验证消息 
  3. 当两个字段都有效时

    All Fields are valid

    图 1.3 所有字段均有效

方法 2:使用数据注释指定业务规则

虽然第一种方法效果很好,但它确实倾向于破坏应用程序的关注点分离。 也就是说,控制器不应包含业务逻辑,例如,业务逻辑属于模型。

Microsoft 在核心 .NET Framework 中提供了一个有效且易于使用的数据验证 API,称为数据注释。它提供了一组属性,我们可以将其应用于数据对象类属性。 这些属性提供了一种非常声明性的方式来将验证规则直接应用于模型。

首先,在 Models 文件夹下创建一个名为 Student (Student.cs) 的模型,并在 Student 类的属性上应用数据注释属性。

using System.ComponentModel.DataAnnotations;
namespace ServerValidation.Models
{
    public class Student
    {
        [Required(ErrorMessage = "Name is Required")]
        public string Name { get; set; }
        [Required(ErrorMessage = "Email is Required")]
        [RegularExpression(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
                            @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
                            @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$",
                            ErrorMessage="Email is not valid")]
        public string Email { get; set; }
    }
} 

现在,在控制器(Controllers 文件夹下的 StudentController 类)中创建一个操作方法,该方法在 post 请求后返回带有模型的视图。

using System.Web.Mvc;
using ServerValidation.Models;
namespace ServerValidation.Controllers
{
    public class StudentController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Index(Student model)
        {
            if (ModelState.IsValid)
            {
                ViewBag.Name = model.Name;
                ViewBag.Email = model.Email;
            }
            return View(model);
        }
    }
} 

之后,我创建了一个视图 (Index.cshtml) 来获取学生详细信息,并在模型数据无效时显示错误消息。

@model ServerValidation.Models.Student 
@{
    ViewBag.Title = "Index";
}
 @if (ViewData.ModelState.IsValid)
    {
        if(@ViewBag.Name != null)
        {
            <b>
                Name : @ViewBag.Name<br />
                Email : @ViewBag.Email
            </b>
        }
    } 
@using (Html.BeginForm()) {
    @Html.ValidationSummary(true) 
    <fieldset>
        <legend>Student</legend> 
        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </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="Create" />
        </p>
    </fieldset>
}  

让我们运行应用程序并执行与第一种方法相同的测试用例。 然后我们将得到相同的结果。

 
© . All rights reserved.