ASP.NET MVC5中的Model验证

Model验证是ASP.NET MVC中的重要部分,它主要用于判断输入的数据类型及值是否符合我们设定的规则,这篇文章就介绍下ASP.NET MVC中Model验证的几种方式。

后台验证

DataAnnotation

DataAnnotation翻译过来是“数据注解”的意思,DataAnnotation命名空间中包含一些用于验证Model的特性,如:RequiredAttribute,CompareAttribute,DisplayAttribute等,我们在创建Model时,将相应的特性性标注到字段上即可实现数据验证。

创建Model:

public class Person
{
    [Display(Name = "姓名")]
    [Required(ErrorMessage = "姓名是必须的!")]
    public string Name { set; get; }
    [Display(Name = "姓名")]
    public int Age { set; get; }
}

View中的代码:

@model EBuy.Website.Models.Person
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        <h3 style="color:red;">
            @Html.ValidationSummary()
        </h3>
    </div>
    <div>
        @using (Html.BeginForm("evaluate", "home", "Post"))
        {
            @Html.LabelFor(Model => Model.Name)
            @Html.TextBoxFor(Model => Model.Name)
            @Html.LabelFor(Model => Model.Age)
            @Html.TextBoxFor(Model => Model.Age)
            <input type="submit" value="提交" />
        }
    </div>
</body>
</html>

Controller中的代码:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Evaluate(Person person)
    {
        if (ModelState.IsValid)
        {
            return Content("evaluate success!");
        }
        return View("Index", person);
    }
}

运行程序:

注意,Age属性上并未标注RequiredAttribute,却依然提示Age字段必须,这是因为Age是int类型,int类型不能为null,对于不能为null的类型,ASP.NET MVC默认为是必须的。除此之外,ASP.NET MVC还会帮助我们进行数据类型的验证,如,若在年龄一栏输入非整数,那么验证将不会通过,且会提示数值不合法。

ValuationAttribute

除了使用DataAnnotation中预定义的一些特性进行数据验证外,我们还可以自定义一些验证特性。这里我们通过覆写DataAnnotation命名空间中ValudationAttribute类的IsValid方法来实现自定义验证。示例代码如下:

public class CheckAgeAttribute : ValidationAttribute
{
    private int _minage;
    public CheckAgeAttribute(int minAge)
    {
        _minage = minAge;
    }
    public override bool IsValid(object value)
    {
        if (value is int)
        {
            var age = value as int?;
            if (age == null)
            {
                return false;
            }
            if (age < _minage)
            {
                return false;
            }
            return true;
        }
        return false;
    }

    public override string FormatErrorMessage(string name)
    {
        return base.FormatErrorMessage(name);
    }
}

标注特性:

public class Person
{
    [Display(Name = "姓名")]
    [Required(ErrorMessage = "姓名是必须的!")]
    [MaxLength(4, ErrorMessage = "太长了")]
    public string Name { set; get; }
    [Display(Name = "年龄")]
    [CheckAge(18, ErrorMessage = "年纪太小!")]
    public int Age { set; get; }
}

然后运行程序:

IValidatableObject

通过实现IValidatableObject接口进行数据的验证,示例代码如下:

public class Person : IValidatableObject
{
    [Display(Name = "姓名")]
    public string Name { set; get; }
    [Display(Name = "年龄")]
    public int Age { set; get; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        Person person = validationContext.ObjectInstance as Person;
        if (person == null)
        {
            yield break;
        }
        if (string.IsNullOrEmpty(person.Name))
        {
            yield return new ValidationResult("您贵姓?");
        }
        if (person.Age < 18)
        {
            yield return new ValidationResult("太年轻了!");
        }
    }
}

运行程序:

IDataErrorInfo

实现IDataErrorInfo接口也可以进行数据的验证,示例代码如下:

public class Person : IDataErrorInfo
{
    [Display(Name = "姓名")]
    public string Name { set; get; }
    [Display(Name = "年龄")]
    public int Age { set; get; }

    public string this[string columnName]
    {
        get
        {
            switch (columnName)
            {
                case "Name":
                    if (string.IsNullOrEmpty(Name))
                    {
                        return "雁过留声,人过留名";
                    }
                    return null;
                case "Age":
                    if (Age < 18)
                    {
                        return "年纪尚轻!";
                    }
                    break;
            }
            return null;
        }
    }

      public string Error
      {
          get
          {
              //若返回值不是""或null,则不管数据是否合法,则验证都不会通过
              //并且会在数据验证成功后显示此处指定的错误信息
              return "";
              //return "出错啦!";
          }
      }
}

运行程序:

前端验证

上述验证均是在服务器端进行的,除此之外我们也可以使用js在客户端进行数据的验证。除了我们自己手写js代码外,ASP.NET MVC也提供了前端验证方法,要启用ASP.NET MVC提供的前端验证方法需要在页面中引入三个js文件:

  • jquery-1.10.2.min.js(也可以是其它版本的jQuery)
  • jquery.validate.min.js
  • jquery.validate.unobtrusive.min.js

然后在配置文件中开启客户端验证(默认是开启的):

<configuration>
    <appSettings>
       <add key="ClientValidationEnabled" value="true"/>
       <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
    </appSettings>
</configuration>

注意:若要使ASP.NET MVC提供的前端验证生效,需要对Model进行数据注解(DataAnnotation)。 引用文件之后,运行程序,然后查看页面源代码,可以看到form中的input标签中多出了 data-val 属性以及其它的和数据注解相关的属性。

对于验证失败的信息,我们需要对用户进行相应的提醒。只需要在<form></form>中添加 @Html.ValidationSummary() 即可。

版权声明

本文为作者原创,版权归作者雪飞鸿所有。 转载必须保留文章的完整性,且在页面明显位置处标明原文链接

如有问题, 请发送邮件和作者联系。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大内老A

ASP.NET Core的路由[3]:Router的创建者——RouteBuilder

在《注册URL模式与HttpHandler的映射关系》演示的实例中,我们总是利用一个RouteBuilder对象来为RouterMiddleware中间件创建所...

4384
来自专栏Jed的技术阶梯

Kafka 消费者旧版低级 API

Kafka 消费者总共有 3 种 API,新版 API、旧版高级 API、旧版低级 API,新版 API 是在 kafka 0.9 版本后增加的,推荐使用新版 ...

2333
来自专栏分布式系统进阶

Influxdb的Meta data分析

Influxdb定义了一个Service:Precreator Serivec(services/precreator/service.go),实现比较简单,周...

1342
来自专栏JavaEdge

高性能队列——Disruptor总论1 背景2 Java内置队列3 ArrayBlockingQueue的问题4 Disruptor的设计方案代码样例性能等待策略Log4j 2应用场景

这里所说的队列是系统内部的内存队列,而不是Kafka这样的分布式队列 Disruptor特性限于3.3.4

2523
来自专栏MasiMaro 的技术博文

Vista 及后续版本的新线程池

在上一篇的博文中,说了下老版本的线程池,在Vista之后,微软重新设计了一套线程池机制,并引入一组新的线程池API,新版线程池相对于老版本的来说,它的可控性更高...

1623
来自专栏不会写文章的程序员不是好厨师

为Hibiscus写文之定时器篇——HashedWheelTimer

去年一年在简书大约写了25篇,在公司内网写了5篇博客。今年定个小目标吧,在简书产出高质量的博客50篇,加油!

1912
来自专栏FreeBuf

NSA的第七种武器|双脉冲星(DoublePulsar) 后门详细分析

1. 引言 NSA的一系列SMB 漏洞利用的背后,最后都会使用到双脉冲星(DoublePulsar)后门。双脉冲星后门是一个无文件内核级的SMB后门。 2. 双...

3374
来自专栏偏前端工程师的驿站

asp.net 解码gb2312下urlencode后的字符串

公司网站前期的网页用了gb2312保存用户数据,而我负责的部分用的是utf8,今天恰好要获取前期录入的数据于是毫无悬念地出现乱码问题,经过一番网上的搜索还是找不...

2165
来自专栏开发与安全

linux系统编程之信号(四):信号的捕捉与sigaction函数

一、内核如何实现信号的捕捉 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复...

3410
来自专栏从零开始学自动化测试

python笔记9-多线程Threading之阻塞(join)和守护线程(setDaemon)

前言 今天小编YOYO请xiaoming和xiaowang吃火锅,吃完火锅的时候会有以下三种场景: - 场景一:小编(主)先吃完了,xiaoming(客)和xi...

3846

扫码关注云+社区

领取腾讯云代金券