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
前言 相信一直关注我的园友都知道,我写的博文都没有特别枯燥理论性的东西,主要是当每开启一门新的技术之旅时,刚开始就直接去看底层实现原理,第一会感觉索然无味,第二也不明白到底为何要这样做,所以只有当你用 ...
随机推荐
- element-ui Pagination组件源码分析整理笔记(七)
element-ui源码的版本是2.4.9 pagination.js import Pager from './pager.vue'; import ElSelect from 'element-u ...
- C#加解密算法
先附上源码 加密解密算法目前已经应用到我们生活中的各个方面 加密用于达到以下目的: 保密性:帮助保护用户的标识或数据不被读取. 数据完整性:帮助保护数据不被更改. 身份验证:确保数据发自特定的一方. ...
- objc与鸭子对象(上)
这是<objc与鸭子对象>的上半部分,<objc与鸭子对象(下)>中介绍了鸭子类型的进阶用法.依赖注入以及demo. 我是前言 鸭子类型(Duck Type)即:“当看到一只鸟 ...
- MediaPlayer音乐播放器、上一首、下一首、播放、停止、自动下一首、进度条
本文介绍MediaPlayer的使用.MediaPlayer可以播放音频和视频,另外也可以通过VideoView来播放视频,虽然VideoView比MediaPlayer简单易用,但定制性不如用Med ...
- ONLYOFFICE连接数20个限制的由来
搜onlyoffice document server的github上的issue,会得到这2个地址https://github.com/ONLYOFFICE/DocumentServer/issue ...
- Android长按事件和点击事件 冲突问题
长按点击的时候默认会触发点击事件,android系统是优先点击的,并且没有返回值:而长按事件是有返回值的,如果返回false,两个事件都会有响应,如果返回true则只响应长按事件.
- Python+Selenium笔记(六):元素定位
(一) 前言 Web应用以及包含超文本标记语言(HTML).层叠样式表(CSS).JS脚本的WEB页面,基于用户的操作(例如点击提交按钮),浏览器向WEB服务器发送请求,WEB服务器响应请求,返 ...
- CSS样式----CSS属性:字体属性和文本属性(图文详解)
本文最初于2015-10-04发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. 本文重要内容 CSS的单位 字体属性 文本属性 定 ...
- Android 的提权(root)原理【转】
Android的内核就是Linux,所以Android获取root其实和Linux获取root权限是一回事儿. su还需要所有者(Owner)是root才能正确的给其他程序赋予root权限.linux ...
- 《Effective C++》 目录:
转自:http://blog.csdn.net/KangRoger/article/details/44706403 目录 条款1:视C++为一个语言联邦 条款2:尽量以const.enum.inli ...