Asp.Net Web API 2第十五课——Model Validation(模型验证)

简介: 原文:Asp.Net Web API 2第十五课——Model Validation(模型验证)前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文参考链接文章地址http://www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api 当客户端发送数据给你的Web API时,你通常希望在做其它处理之前先对数据进行验证。
原文: Asp.Net Web API 2第十五课——Model Validation(模型验证)

前言

阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html

本文参考链接文章地址http://www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api

当客户端发送数据给你的Web API时,你通常希望在做其它处理之前先对数据进行验证。

Data Annotations——数据注解

 在ASP.NET Web API中,你可以使用System.ComponentModel.DataAnnotations命名空间的注解属性来设置模型属性的验证规则。考虑以下模型:

public class Product
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }
    public decimal Price { get; set; }

    [Range(0,999)]
    public double Weight { get; set; }
}

如果你曾在ASP.NET MVC中使用过模型验证,这看上去是类似的。Required注解属性说明Name属性必须不为空。Range注解属性说明Weight必须在0-999之间。

假设客户端发送了一个带有下列JSON表示的POST请求:

{ "Id":4, "Price":2.99, "Weight":5 }

你可以看出,客户端并未包含被标记成required的Name属性。当Web API将该JSON转换成Product实例时,它会根据这些验证注解属性对Product进行验证。在控制器动作中,你可以检查该模型是否有效:

public class ProductsController : ApiController
{
    public HttpResponseMessage Post(Product product)
    {
        if (ModelState.IsValid)
        {
            // Do something with the product (not shown).
            // 用product做一些事(未表示出来)

            return new HttpResponseMessage(HttpStatusCode.OK);
        }
        else
        {
            return new HttpResponseMessage(HttpStatusCode.BadRequest);
        }
    }
}

模型验证并不保证客户端数据是安全的。在应用程序的其它层面可能会需要附加验证(例如,数据层可能会强制外键约束)。

{"Id":4, "Name":"Gizmo"}

此处,客户端并未指定Price或Weight的值。JSON格式化器会将默认值(这里是零)赋给这些缺失的属性。

Under-Posting(递交不足)”:当客户端遗漏了某些属性时,便会发生“Under-posting”。例如,假设客户端发送如下:

此时模型的状态是有效的,因为零是这些属性的有效值。这是否是一个问题取决于你所处的场景。例如,在一个更新操作中,你可能希望区分出“零”与“未设置”。为了强迫客户端要设置一个值,将该属性构造成nullable(可空的),并设置Required注解属性:

[Required]
public decimal? Price { get; set; }

Over-Posting(过份递交)”:客户端也可能发送比期望还多的数据。例如:

{"Id":4, "Name":"Gizmo", "Color":"Blue"}

此处,JSON包含了Product模型中存在的属性(“Color”)。在这种情况下,JSON格式化器会简单地忽略该值(XML格式化器却不同)。若你的模型具有只读属性,Over-posting会产生问题。例如:

public class UserProfile
{
    public string Name { get; set; }
    public Uri Blog { get; set; }
    public bool IsAdmin { get; set; }  // uh-oh!(啊哦!)
}

如果你不想让用户对IsAdmin属性进行更新,并将其提升给管理员。最安全的策略是使用一个与允许客户端发送严格匹配的模型类:

public class UserProfileDTO
{
    public string Name { get; set; }
    public Uri Blog { get; set; }
    // Leave out "IsAdmin"
    // 略去了"IsAdmin"
}

Handling Validation Errors——处理验证错误

 当验证失败时,Web API并不会自动地将错误返回给客户端。这取决于控制器动作对模型状态及响应进行适当的检查。

你也可以创建一个动作过滤器,以便在控制器动作被调用之前,检查模型的状态。以下代码演示了一个例子:

using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Web.Http.ModelBinding;

public class ModelValidationFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (actionContext.ModelState.IsValid == false)
        {
            // Return the validation errors in the response body.
            // 在响应体中返回验证错误
            var errors = new Dictionary<string, IEnumerable<string>>();
            foreach (KeyValuePair<string, ModelState> keyValue in actionContext.ModelState)
            {
                errors[keyValue.Key] = keyValue.Value.Errors.Select(e => e.ErrorMessage);
            }

            actionContext.Response = 
                actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, errors);
        }
    }
}

如果模型验证失败,此过滤器会返回一个含有验证错误的HTTP响应。在此情况下,不会调用控制器动作。

HTTP/1.1 400 Bad Request
Server: ASP.NET Development Server/10.0.0.0
Date: Fri, 20 Jul 2012 21:42:18 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 239
Connection: Close

{
    "product": [
        "Required property 'Name' not found in JSON. Line 1, position 18."
    ],

    "product.Name": [
        "The Name field is required."
    ],

    "product.Weight": [
        "The field Weight must be between 0 and 999."
    ]
}

如果你正在使用CodePlex上最新版的Web API,可以使用HttpError类将验证错误返回给客户端。HttpError类在RC版(指Web API的预览版)中无效。

你可以将此过滤器全局性地运用于所有Web API控制器。在Application_Start方法中,将此过滤器添加到HttpConfiguration.Filters集合:

protected void Application_Start()
{
    // ...

    GlobalConfiguration.Configuration.Filters.Add(new ModelValidationFilterAttribute());
}

另一种可选办法是,通过将此过滤器作为注解属性进行添加,你可以将它运用于个别控制器或控制器动作:

public class ProductsController : ApiController
{
    [ModelValidationFilter]
    public HttpResponseMessage Post(Product product)
    {
        // ...
    }
}
目录
相关文章
|
1月前
|
人工智能 缓存 API
谷歌发布MediaPipe LLM Inference API,28亿参数模型本地跑
【2月更文挑战第24天】谷歌发布MediaPipe LLM Inference API,28亿参数模型本地跑
78 3
谷歌发布MediaPipe LLM Inference API,28亿参数模型本地跑
|
2月前
|
分布式计算 API Linux
通义千问API:找出两篇文章的不同
本章我们将介绍如何利用大模型开发一个文档比对小工具,我们将用这个工具来给互联网上两篇内容相近但版本不同的文档找找茬,并且我们提供了一种批处理文档比对的方案
|
2月前
|
自然语言处理 搜索推荐 API
通义千问API:用4行代码对话大模型
本章将通过一个简单的例子,让你快速进入到通义千问大模型应用开发的世界。
221915 104
通义千问API:用4行代码对话大模型
|
2月前
|
机器学习/深度学习 API 开发工具
通义千问API入门教程
本教程将带你从零开始,快速了解如何通过 API 使用通义千问大模型,并尝试使用大模型 API 开发一些简单的应用应用到工作中,提升效率。
12830 10
|
2月前
|
机器学习/深度学习 JSON 监控
智能定价模型:借助API实时更新商品价格信息
在电子商务的迅猛发展中,价格战成为商家间常见的竞争方式。然而,一成不变的价格策略无法满足市场的即时需求和消费者的多变偏好。因此,智能定价(也称为动态定价)成为了电商平台提升市场竞争力的关键工具。智能定价模型通过实时监控市场数据和消费者行为,自动调整商品价格以最大化收益或实现其他商业目标。本文将深入探讨如何利用API技术实现智能定价,并提供一个Python代码示例来指导读者进行实时价格更新。
|
3月前
|
API C++
socket编程之常用api介绍与socket、select、poll、epoll高并发服务器模型代码实现(1)
前言   本文旨在学习socket网络编程这一块的内容,epoll是重中之重,后续文章写reactor模型是建立在epoll之上的。
34 0
|
3月前
|
监控 安全 Linux
socket编程之常用api介绍与socket、select、poll、epoll高并发服务器模型代码实现(3)
高并发服务器模型-poll poll介绍   poll跟select类似, 监控多路IO, 但poll不能跨平台。其实poll就是把select三个文件描述符集合变成一个集合了。
36 0
|
22小时前
|
机器学习/深度学习 存储 计算机视觉
r语言中对LASSO回归,Ridge岭回归和弹性网络Elastic Net模型实现-4
r语言中对LASSO回归,Ridge岭回归和弹性网络Elastic Net模型实现
25 11
|
7天前
|
算法
r语言中对LASSO回归,Ridge岭回归和Elastic Net模型实现
r语言中对LASSO回归,Ridge岭回归和Elastic Net模型实现
15 1
|
7天前
|
算法
r语言中对LASSO,Ridge岭回归和Elastic Net模型实现
r语言中对LASSO,Ridge岭回归和Elastic Net模型实现
11 0