本文讨论ASP.NET Core 2.1中与ASP.NET Core MVC / Web API控制器中的模型绑定相关的功能。虽说这是一个功能,但从我的角度来看,它更像是一个错误修复!

请注意,我使用的是 NET Core 2.1 Preview 1,正式版发布后,功能可能存在变动。

ASP.NET Core 2.0 模型验证

模型验证是ASP.NET Core MVC 管线的重要组成部分。有很多方法可以注入到验证层(例如使用FluentValidation),最常见的方法可能是使用来自System.ComponentModel的验证标记来修饰绑定模型。 例如:

public class UserModel
{
[Required, EmailAddress]
public string Email { get; set; } [Required, StringLength(1000)]
public string Name { get; set; }
}

如果您在控制器的操作方法中使用UserModelMvcMiddleware则会自动创建对象的新实例,绑定模型的属性并使用如下三个来源对其进行验证:

  1. 表单 - 当使用POST将表单发送到服务器时,发送到HTTP请求的主体中;
  2. 路由 - 在匹配路由后从URL段或默认值中获取;
  3. 查询字符串 - 在URL的末尾传递。

请注意,目前,作为JSON发送的数据默认情况下不会被绑定。如果您希望绑定请求体中的JSON数据,则需要使用此处所述[FromBody]标记修饰模型。

在控制器Action方法中,可以简单地检查ModelState属性,确定提供的数据是否有效:

public class CheckoutController : Controller
{
public IActionResult SaveUser(UserModel model)
{
if(!ModelState.IsValid)
{
// Something wasn't valid on the model
return View(model);
} // The model passed validation, do something with it
}
}

这是非常标准的MVC内容,但是如果您不想创建整个绑定模型,但仍想验证传入数据,该怎么办?

ASP.NET Core 2.0 顶级参数

DataAnnotation标记默认MVC验证系统使用的属性不必应用于类的属性,它们也可以应用于参数。这可能会导致您认为您可以完全替换UserModel上面的示例中的以下内容:

MVC默认验证系统使用的DataAnnotation标记不一定应用于类的属性,它们同样可以应用于参数。这可能会导致您认为可以完全替换上面示例中的UserModel,如下所示:

public class CheckoutController : Controller
{
public IActionResult SaveUser(
[Required, EmailAddress] string Email
[Required, StringLength(1000)] string Name)
{
if(!ModelState.IsValid)
{
// Something wasn't valid on the model
return View(model);
} // The model passed validation, do something with it
}
}

不幸的是,这是行不通的!在绑定属性时,验证属性将被忽略,并且ModelState.IsValid始终是true

ASP.NET Core 2.1中的顶级参数

幸运的是,ASP.NET Core团队意识到了这个问题,并且已经将修补程序合并为ASP.NET Core 2.1的一部分。因此,上一节中的代码的行为与您所期望的一样,参数经过验证,并相应地进行了ModelState.IsValid更新。

作为这项工作的一部分,您现在还可以使用[BindRequired]标记修饰参数。当绑定非空值类型时,此标记很重要,因为使用[Required]标记对这些属性并不能提供预期的行为。

这意味着您现在可以执行以下操作,并确保testId参数已从路由参数中正确绑定,并且qty参数已从查询字符串中绑定。在ASP.NET Core 2.1之前,它甚至不能编译!

[HttpGet("test/{testId}")]
public IActionResult Get([BindRequired, FromRoute] Guid testId, [BindRequired, FromQuery] int qty)
{
if(!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// Valid and bound
}

对于这个问题可以查阅我之前的博客:《ASP.NET Core MVC中的 [Required]与[BindRequired]》

总结

在ASP.NET Core 2.0及以下版本中,应用于顶级参数的验证标记将被忽略,并且ModelState不会更新。只考虑复杂模型类型的验证参数。

在ASP.NET Core 2.1中,验证标记现在将在顶级参数上得到遵守。更重要的是,您可以将[BindReqired]标记应用于参数。

ASP.NET Core 2.1 增加了很多新特性。这是一些不错的小改进之一,它使事情变得更容易,更一致 -- 我喜欢这种改变。

翻译自https://andrewlock.net/coming-in-asp-net-core-2-1-top-level-mvc-parameter-validation/

ASP.NET Core MVC 2.1 顶级参数验证的更多相关文章

  1. 创建ASP.NET Core MVC应用程序(6)-添加验证

    创建ASP.NET Core MVC应用程序(6)-添加验证 DRY原则 DRY("Don't Repeat Yourself")是MVC的设计原则之一.ASP.NET MVC鼓励 ...

  2. asp.net core MVC 控制器,接收参数,数据绑定

    1.参数 HttpRequest HttpRequest 是用户请求对象 QueryString Form Cookie Session Header 实例: public IActionResult ...

  3. ASP.NET Core MVC的路由参数中:exists后缀有什么作用,顺便谈谈路由匹配机制

    我们在ASP.NET Core MVC中如果要启用Area功能,那么会看到在Startup类的Configure方法中是这么定义Area的路由的: app.UseMvc(routes => { ...

  4. ASP.NET Core MVC 概述

    https://docs.microsoft.com/zh-cn/aspnet/core/mvc/overview?view=aspnetcore-2.2 ASP.NET Core MVC 概述 20 ...

  5. asp.net core mvc权限控制:在视图中控制操作权限

    在asp.net core mvc中提供了权限验证框架,前面的文章中已经介绍了如何进行权限控制配置,权限配置好后,权限验证逻辑自动就会执行,但是在某些情况下,我们可能需要在代码里或者视图中通过手工方式 ...

  6. ASP.NET Core MVC里面Razor如何获取URL参数

    原文:ASP.NET Core MVC里面Razor如何获取URL参数 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https:// ...

  7. ASP.NET Core MVC/WebAPi 模型绑定探索

    前言 相信一直关注我的园友都知道,我写的博文都没有特别枯燥理论性的东西,主要是当每开启一门新的技术之旅时,刚开始就直接去看底层实现原理,第一会感觉索然无味,第二也不明白到底为何要这样做,所以只有当你用 ...

  8. ASP.NET Core 中文文档 第二章 指南(2)用 Visual Studio 和 ASP.NET Core MVC 创建首个 Web API

    原文:Building Your First Web API with ASP.NET Core MVC and Visual Studio 作者:Mike Wasson 和 Rick Anderso ...

  9. ASP.NET Core 中文文档 第四章 MVC(01)ASP.NET Core MVC 概览

    原文:Overview of ASP.NET Core MVC 作者:Steve Smith 翻译:张海龙(jiechen) 校对:高嵩 ASP.NET Core MVC 是使用模型-视图-控制器(M ...

随机推荐

  1. Linux显示服务器完整的状态信息

    Linux显示服务器完整的状态信息 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ apachectl [fullstatus] Usage: /usr/sbi ...

  2. Request对象实现请求转发区别

    servlet请求转发与重定向的区别: request.setAttribute("test","hello"); request.getRequestDisp ...

  3. Linux之权限管理

    一.文件基本权限 1) 基本权限的修改 第一位"-"为文件类型(-代表文件:d代表目录:l代表软链接文件即快捷方式),后面每3位一组. -rw-r--r-- rw-   u所有者 ...

  4. javax顶层接口分析

    1.Servlet接口分析 此接口是Servlet的最顶层接口,其中定义了Servlet生命周期相关的方法,所有Servlet都必须实现.此接口中的方法有以下几个: public void init( ...

  5. 【BZOJ1010】【HNOI2008】玩具装箱(斜率优化,动态规划)

    [BZOJ1010][HNOI2008]玩具装箱 题面 题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一 ...

  6. 2018java平均工资,想转行学java的快点上车

    很多人选择工作的原因很简单:要么有钱,要么自己开心,当然绝大多数人是既没有钱也不开心...(现实就是这么残酷).哪有钱多事少的活,请告诉我,我第一个去!!我想大部分人对java充满好奇的一个原因就是钱 ...

  7. Go实现短url项目

    首先说一下这种业务的应用场景: 把一个长url转换为一个短url网址 主要用于微博,二维码,等有字数限制的场景 主要实现的功能分析: 把长url的地址转换为短url地址 通过短url获取对应的原始长u ...

  8. Django高级部分

    Django高级部分 1.上传图片: 当Django在处理文件上传的时候,文件数据被保存在request.FILES,FILES中的每个键为<input type="file" ...

  9. 用Go自己实现配置文件热加载功能

    说到配置文件热加载,这个功能在很多框架中都提供了,如beego,实现的效果就是当你修改文件后,会把你修改后的配置重新加载到配置文件中,而不用重启程序,这个功能在日常中还是非常实用的,毕竟很多时候,线上 ...

  10. Python创建容器和集合之源码分析

    _collections_abc.py文件中提供了许多抽象基类,这些类将集合分解成许多互相独立的属性集 __all__ = ["Awaitable", "Coroutin ...