ASP.NET Core MVC 模型绑定 (转载)
ASP.NET Core MVC的Model Binding会将HTTP Request数据,以映射的方式对应到参数中。基本上跟ASP.NET MVC差不多,但能Binding的来源更多了一些。
本篇将介绍ASP.NET Core的Model Binding。
Model Binding
要接收Client 传送来的数据,可以通过Action 的参数接收,如下:
- using Microsoft.AspNetCore.Mvc;
- namespace MyWebsite.Controllers
- {
- public class HomeController : Controller
- {
- public IActionResult Index(int id)
- {
- return Content($"id: {id}");
- }
- }
- }
id就是从HTTP Request的内容被Binding的Model参数。
预设的Model Binding会从HTTP Request的三个地方取值(优先顺序由上到下):
- Form
透过HTTP POST的form取值。如下图:
- Route
是通过MVC Route URL取值。
如:http://localhost:5000/Home/Index/2,id取出的值就会是2。
- Query
是通过URL Query参数取值。
如:http://localhost:5000/Home/Index?id=1,id取出的值就会是1。
如果三者都传入的话,会依照优先顺序取值Form > Route > Query。
Binding Attributes
除了预设的三种Binding 来源外,还可以通过Model Binding Attributes 从HTTP Request 的其他数据中Binding。有以下6 种:
- [FromHeader]
从HTTP Header取值。
- [FromForm]
通过HTTP POST的form取值。
- [FromRoute]
是通过MVC Route URL取值。
- [FromQuery]
是通过URL Query参数取值。
- [FromBody]
从HTTP Body取值,通常用于取JSON, XML。
ASP.NET Core MVC预设的序列化是使用JSON,如果要传XML格式做Model Binding的话,要在MVC服务加入XmlSerializerFormatters,如下:
Startup.cs
- // ...
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddMvc()
- .AddXmlSerializerFormatters();
- }
- [FromServices]
这个比较特别,不是从HTTP Request取值,而是从DI容器取值。
DI预设是使用Constructor Injection,但Controller可能会因为每个Action用到不一样的Service导致很多参数,所以也可以在Action注入Service。
范例程序
- // ...
- public class HomeController : Controller
- {
- public IActionResult FirstSample(
- [FromHeader]string header,
- [FromForm]string form,
- [FromRoute]string id,
- [FromQuery]string query)
- {
- return Content($"header: {header}, form: {form}, id: {id}, query: {query}");
- }
- public IActionResult DISample([FromServices] ILogger<HomeController> logger)
- {
- return Content($"logger is null: {logger == null}.");
- }
- public IActionResult BodySample([FromBody]UserModel model)
- {
- return Ok(model);
- }
- }
- // ...
- public class UserModel
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public string Email { get; set; }
- public string PhoneNumber { get; set; }
- public string Address { get; set; }
- }
输出结果
FirstSample输出结果:
DISample输出结果:
http://localhost:5000/Home/DISample
- logger is null: False.
BodySample输出结果:
- JSON
- XML
Model 验证
Model Binding 也可以顺便帮忙验证字段数据,只要在字段的属性上面带上Validation Attributes,如下:
- using System.ComponentModel.DataAnnotations;
- // ...
- public class UserModel
- {
- [Required]
- public int Id { get; set; }
- [RegularExpression(@"\w+")]
- [StringLength(, MinimumLength = )]
- public string Name { get; set; }
- [EmailAddress]
- public string Email { get; set; }
- [Phone]
- public string PhoneNumber { get; set; }
- [StringLength()]
- public string Address { get; set; }
- }
然后在Action 加上判断:
Controllers\HomeController.cs
- using Microsoft.AspNetCore.Mvc;
- namespace MyWebsite.Controllers
- {
- public class HomeController : Controller
- {
- // ...
- public IActionResult BodySample([FromBody]UserModel model)
- {
- // 由于 Id 是 int 类型,int 默认为 0
- // 虽然带上了 [Required],但不是 null 所以算是有值。
- if (model.Id < )
- {
- ModelState.AddModelError("Id", "Id not exist");
- }
- if (ModelState.IsValid)
- {
- return Ok(model);
- }
- return BadRequest(ModelState);
- }
- }
- }
输入错误数据的输出结果:
.NET Core提供了很多的Validation Attributes,可以参考官网:
System.ComponentModel.DataAnnotations
自定义Validation Attributes
如果.NET Core提供的Validation Attributes不够用还可以自己做。
例如上述范例的数据模型多了生日字段,需要验证年龄:
- using System;
- using System.ComponentModel.DataAnnotations;
- namespace MyWebsite.Attributes
- {
- public class AgeCheckAttribute : ValidationAttribute
- {
- public int MinimumAge { get; private set; }
- public int MaximumAge { get; private set; }
- public AgeCheckAttribute(int minimumAge, int maximumAge)
- {
- MinimumAge = minimumAge;
- MaximumAge = maximumAge;
- }
- protected override ValidationResult IsValid(object value, ValidationContext validationContext)
- {
- var date = Convert.ToDateTime(value);
- if (date.AddYears(MinimumAge) > DateTime.Today
- || date.AddYears(MaximumAge) < DateTime.Today)
- {
- return new ValidationResult(GetErrorMessage(validationContext));
- }
- return ValidationResult.Success;
- }
- private string GetErrorMessage(ValidationContext validationContext)
- {
- // 有帶 ErrorMessage 的话优先使用
- // [AgeCheck(18, 120, ErrorMessage="xxx")]
- if (!string.IsNullOrEmpty(this.ErrorMessage))
- {
- return this.ErrorMessage;
- }
- // 自定义错误信息
- return $"{validationContext.DisplayName} can't be in future";
- }
- }
- }
参考
Overview of ASP.NET Core MVC
Introduction to model validation in ASP.NET Core MVC
ASP.NET CORE 2.0 MVC MODEL BINDING
ASP.NET CORE 2.0 MVC MODEL VALIDATION
ASP.NET Core MVC 模型绑定 (转载)的更多相关文章
- ASP.NET Core MVC 模型绑定用法及原理
前言 查询了一下关于 MVC 中的模型绑定,大部分都是关于如何使用的,以及模型绑定过程中的一些用法和概念,很少有关于模型绑定的内部机制实现的文章,本文就来讲解一下在 ASP.NET Core MVC ...
- .net core mvc 模型绑定 之 json and urlencoded
.net core mvc 模型绑定, FromQuery,对应 url 中的 urlencoded string ("?key1=value1&key2=value2") ...
- ASP.NET Core 中文文档 第四章 MVC(01)ASP.NET Core MVC 概览
原文:Overview of ASP.NET Core MVC 作者:Steve Smith 翻译:张海龙(jiechen) 校对:高嵩 ASP.NET Core MVC 是使用模型-视图-控制器(M ...
- ASP.NET Core MVC 概述
https://docs.microsoft.com/zh-cn/aspnet/core/mvc/overview?view=aspnetcore-2.2 ASP.NET Core MVC 概述 20 ...
- 你所不知道的ASP.NET Core MVC/WebApi基础系列(二)
前言 好久没冒泡了,算起来估计有快半年没更新博客了,估计是我第一次停更如此之久,人总有懒惰的时候,时间越长越懒惰,但是呢,不学又不行,持续的惰性是不行dei,要不然会被时光所抛弃,技术所淘汰,好吧,进 ...
- 你所不知道的ASP.NET Core MVC/WebApi基础系列 (二)
转自博客:https://www.cnblogs.com/CreateMyself/p/10604293.html 前言 本节内容,我们来讲讲.NET Core当中的模型绑定系统.模型绑定原理.自定义 ...
- ASP.NET Core 入门教程 3、ASP.NET Core MVC路由入门
一.前言 1.本文主要内容 ASP.NET Core MVC路由工作原理概述 ASP.NET Core MVC带路径参数的路由示例 ASP.NET Core MVC固定前/后缀的路由示例 ASP.NE ...
- ASP.NET Core 入门笔记4,ASP.NET Core MVC路由入门
敲了一部分,懒得全部敲完,直接复制大佬的博客了,如有侵权,请通知我尽快删除修改 摘抄自https://www.cnblogs.com/ken-io/p/aspnet-core-tutorial-mvc ...
- ASP.NET Core MVC/WebAPi 模型绑定探索 转载https://www.cnblogs.com/CreateMyself/p/6246977.html
前言 相信一直关注我的园友都知道,我写的博文都没有特别枯燥理论性的东西,主要是当每开启一门新的技术之旅时,刚开始就直接去看底层实现原理,第一会感觉索然无味,第二也不明白到底为何要这样做,所以只有当你用 ...
随机推荐
- AngularJS学习之 angular-file-upload控件使用方法
1.官方链接 https://github.com/nervgh/angular-file-upload 2.安装到项目中 bower install angular-file-upload(安装完成 ...
- SwipeRefreshLayout嵌套ScrollView实现下拉刷新
API doc:http://developer.android.com/reference/android/support/v4/widget/SwipeRefreshLayout.html 首先须 ...
- nginx 配置 非80 的其他 端口
如果nginx的监听端口不是默认的80端口,改为其他非80端口后,后端服务tomcat中的request.getServerPort()方法无法获得正确的端口号,仍然返回到80端口.在response ...
- ElementUI制作树形表组件
提要 最近项目中需要用到树形表格来描述部门.区域之间的父子展开关系.但是已经在项目中使用的Vue的成熟组件ElementUI以及iViewUI组件都没有提供相应的树形表格组件,无奈找了其他替代方案也都 ...
- qt调用js,js调用qt
<html> <script language="JavaScript"> function qtcalljs() { alert("sdfsd& ...
- Prometheus Node_exporter 详解
Basic CPU / Mem / Disk Info https://www.cnblogs.com/qianyuliang/p/10479515.html Basic CPU / Mem / Di ...
- Linux 中 FQDN 查询及设置
FQDN:(Fully Qualified Domain Name)全限定域名:同时带有主机名和域名的名称 其实就是标注一个主机的完整域名.比如我的域名为 ifrom.top 那么它的邮件服务器的主机 ...
- man -k : nothing appropriate.
➜ workplace man -k zip zip: nothing appropriate. 出现这种情况,是索引库没有建立. man 和 whatis 共用一个索引库的. 我们使用 man w ...
- 【8】python文件的读写方法
(1).读文件的步骤: (1)打开文件 open(path,flag,encoding,[errors]) path:打开路径 flag:打开方式 r(只读) rb(二进制格式) r+(可以读写) w ...
- 题解 P1120 【小木棍 [数据加强版]】
题面 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编程帮 ...