ASP.NET Core 2 学习笔记(九)模型绑定
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(20, MinimumLength = 4)]
public string Name { get; set; } [EmailAddress]
public string Email { get; set; } [Phone]
public string PhoneNumber { get; set; } [StringLength(200)]
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 < 1)
{
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
老司机发车啦:https://github.com/SnailDev/SnailDev.NETCore2Learning
ASP.NET Core 2 学习笔记(九)模型绑定的更多相关文章
- Asp.Net Core WebApi学习笔记(四)-- Middleware
Asp.Net Core WebApi学习笔记(四)-- Middleware 本文记录了Asp.Net管道模型和Asp.Net Core的Middleware模型的对比,并在上一篇的基础上增加Mid ...
- sql server 关于表中只增标识问题 C# 实现自动化打开和关闭可执行文件(或 关闭停止与系统交互的可执行文件) ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例 将小写阿拉伯数字转换成大写的汉字, C# WinForm 中英文实现, 国际化实现的简单方法 ASP.NET Core 2 学习笔记(六)ASP.NET Core 2 学习笔记(三)
sql server 关于表中只增标识问题 由于我们系统时间用的过长,数据量大,设计是采用自增ID 我们插入数据的时候把ID也写进去,我们可以采用 关闭和开启自增标识 没有关闭的时候 ,提示一下错 ...
- ASP.NET Core 2 学习笔记(七)路由
ASP.NET Core通过路由(Routing)设定,将定义的URL规则找到相对应行为:当使用者Request的URL满足特定规则条件时,则自动对应到相符合的行为处理.从ASP.NET就已经存在的架 ...
- ASP.NET Core 2 学习笔记(十三)Swagger
Swagger也算是行之有年的API文件生成器,只要在API上使用C#的<summary />文件注解标签,就可以产生精美的线上文件,并且对RESTful API有良好的支持.不仅支持生成 ...
- ASP.NET Core 2 学习笔记(十二)REST-Like API
Restful几乎已算是API设计的标准,通过HTTP Method区分新增(Create).查询(Read).修改(Update)和删除(Delete),简称CRUD四种数据存取方式,简约又直接的风 ...
- ASP.NET Core 2 学习笔记(十)视图
ASP.NET Core MVC中的Views是负责网页显示,将数据一并渲染至UI包含HTML.CSS等.并能痛过Razor语法在*.cshtml中写渲染画面的程序逻辑.本篇将介绍ASP.NET Co ...
- ASP.NET Core 2 学习笔记(一)开始
原文:ASP.NET Core 2 学习笔记(一)开始 来势汹汹的.NET Core似乎要取代.NET Framework,ASP.NET也随之发布.NET Core版本.虽然名称沿用ASP.NET, ...
- 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(九)-- 单元测试
本篇将结合这个系列的例子的基础上演示在Asp.Net Core里如何使用XUnit结合Moq进行单元测试,同时对整个项目进行集成测试. 第一部分.XUnit 修改 Project.json 文件内容, ...
- ASP.NET Core MVC学习笔记
最近由于疫情紧张,遂在家办公,在领导的带领下,学习了一下.Net Core MVC. 一,构建web应用 1.选择c#-所有平台-web 找到ASP.NET Core web应用程序 2.项目命名之 ...
随机推荐
- Spark记录-Spark性能优化解决方案
Spark性能优化的10大问题及其解决方案 问题1:reduce task数目不合适解决方式:需根据实际情况调节默认配置,调整方式是修改参数spark.default.parallelism.通常,r ...
- POJ - 3279 Fliptile (枚举)
http://poj.org/problem?id=3279 题意 一个m*n的01矩阵,每次翻转(x,y),那么它上下左右以及本身就会0变1,1变0,问把矩阵变成全0的,最小需要点击多少步,并输出最 ...
- 我的Mac中毒了,病毒居然叫做MacPerformance
禁用 ReportCrash 直接干掉进程肯定不管用,从名字就知道这个进程会自动被触发,除非修改系统配置. Google 了一下,发现很简单,在 terminal 里执行 launchctl unlo ...
- elasticsearch 基本配置
基本配置elasticsearch的config文件夹里面有两个配置文件:elasticsearch.yml .logging.yml.jvm.options 第一个是es的基本配置文件,第二个是日志 ...
- Ansi与Unicode编码
视频教程:Ansi与Unicode编码 大家在编程时经常遇到的数据类型: ● Ansi: char 代表一个字符 (CHAR) char * 代表一个字符串指针 (PCHAR PST ...
- 前序遍历and中序遍历and后序遍历
根据根节点的出现的时间确定前.中.后遍历. 1: 前序遍历首先访问根结点然后遍历左子树,最后遍历右子树.在遍历左.右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树. 前序遍历结果:ABDEC ...
- [JLOI2015]装备购买 (高斯消元)
[JLOI2015]装备购买 \(solution:\) 首先这道题的题面已经非常清晰的告诉我们这就是线性空间高斯消元的一道题(可以用某些装备来表示另一件装备,这已经不能再明显了),只是这道题要求我们 ...
- Docker镜像原理
⒈是什么? 镜像是一种轻量级.可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码.运行时.库.环境变量以及配置文件等. 引用 UnionFs( ...
- Linux驱动技术(三) _DMA编程【转】
转自:https://www.cnblogs.com/xiaojiang1025/archive/2017/02/11/6389194.html DMA即Direct Memory Access,是一 ...
- Ubuntu 16.04配置国内高速apt-get更新源【转】
转自:https://blog.csdn.net/twang0x80/article/details/79782753 Ubuntu 16.04下载软件速度有点慢,因为默认的是从国外下载软件,那就更换 ...