.NET 云原生架构师训练营(模块二 基础巩固 MVC终结点)--学习笔记
2.3.4 Web API -- MVC终结点
- MVC与MVVM
- 模型绑定
- 自定义模型绑定器
- 模型验证
- 返回数据处理
MVC与MVVM
MVC
ASP.NET Core MVC 概述:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/overview?view=aspnetcore-5.0

MVVM
ASP.NET Core 中的 Razor Pages 介绍:https://docs.microsoft.com/zh-cn/aspnet/core/razor-pages/?view=aspnetcore-5.0&tabs=visual-studio
Razor Pages 没有 Controller,Model 中可以包含方法

ASP.NET Core MVC 注入
services.AddControllers();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
MVC Endpoint

模型绑定
- 什么是模型绑定
- 来源有哪些
- 复杂的数据绑定
ASP.NET Core 中的模型绑定:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/model-binding?view=aspnetcore-5.0
什么是模型绑定
控制器和 Razor 页面处理来自 HTTP 请求的数据。 例如,路由数据可以提供一个记录键,而发布的表单域可以为模型的属性提供一个值。 编写代码以检索这些值,并将其从字符串转换为 .NET 类型不仅繁琐,而且还容易出错。
模型绑定会自动化该过程。 模型绑定系统:
- 从各种源(如路由数据、表单域和查询字符串)中检索数据。
- Razor在方法参数和公共属性中向控制器和页面提供数据。
- 将字符串数据转换为 .NET 类型。
- 更新复杂类型的属性。
来源有哪些
- [FromQuery] -从查询字符串获取值。
- [FromRoute] -从路由数据中获取值。
- [FromForm] -从已发布的表单字段中获取值。
- [FromBody] -从请求正文中获取值。
- [FromHeader] -从 HTTP 标头中获取值。
从路由数据中获取值
[HttpGet]
[Route("option/{id}")]
public IActionResult GetOption([FromRoute] int id)
{
return Ok(new {id});
}
从查询字符串获取值
[HttpGet]
[Route("option/{id}")]
public IActionResult GetOption([FromRoute] int id, [FromQuery] string name)
{
return Ok(new {id, name});
}
从 HTTP 标头中获取值
[HttpGet]
[Route("option/{id}")]
public IActionResult GetOption([FromRoute] int id, [FromQuery] string name,[FromHeader] string termId)
{
return Ok(new {id, name, termId});
}
从已发布的表单字段中获取值
[HttpPost]
[Route("option/from")]
public IActionResult CreateOption([FromForm] string name, [FromForm] string id)
{
return Ok(new {name, id});
}
从请求正文中获取值
[HttpPost]
[Route("option/body")]
public IActionResult CreateOption([FromBody] string name)
{
return Ok(name);
}
复杂的数据绑定
- 对象
- 集合
- 字典
对象
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
}
[HttpPost]
[Route("option/body")]
public IActionResult CreateOption([FromBody] Student student)
{
return Ok(student);
}
字典
[HttpGet]
[Route("option")]
public IActionResult GetOption([FromQuery] Dictionary<int, string> dic)
{
var students = new List<Student>();
foreach (var item in dic)
{
students.Add(new Student {Id = item.Key, Name = item.Value});
}
return Ok(students);
}
启动程序,访问:https://localhost:5001/config/option?dic[1001]=ming$dic[1002]=rank&dic[1003]=abc
输出:
[{"id":1001,"name":"ming$dic[1002]=rank"},{"id":1003,"name":"abc"}]
自定义模型绑定器
ASP.NET Core 中的自定义模型绑定:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/advanced/custom-model-binding?view=aspnetcore-5.0
ModelBinder
[ModelBinder(BinderType = typeof(AuthorEntityBinder))]
public class Author
{
public int Id { get; set; }
public string Name { get; set; }
public string GitHub { get; set; }
public string Twitter { get; set; }
public string BlogUrl { get; set; }
}
public class AuthorEntityBinder : IModelBinder
ModelBinderProvider
public class AuthorEntityBinderProvider : IModelBinderProvider
services.AddControllers(options =>
{
options.ModelBinderProviders.Insert(0, new AuthorEntityBinderProvider());
});
模型验证
- 什么是模型验证
- 模型验证的特性与消息
- FluentValidation
什么是模型验证
ASP.NET Core MVC 和页面中的模型验证 Razor:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/validation?view=aspnetcore-5.0
Web 应用负责检查 ModelState.IsValid 并做出相应响应
if (!ModelState.IsValid)
{
return Page();
}
模型验证的特性与消息
- [CreditCard]:验证属性是否具有信用卡格式。
- [Compare]:验证模型中的两个属性是否匹配。
- [EmailAddress]:验证属性是否具有电子邮件格式。
- [Phone]:验证属性是否具有电话号码格式。
- [Range]:验证属性值是否在指定的范围内。
- [RegularExpression]:验证属性值是否与指定的正则表达式匹配。
- [Required]:验证字段是否不为 null。
- [StringLength]:验证字符串属性值是否不超过指定长度限制。
- [Url]:验证属性是否具有 URL 格式。
- [Remote]:通过在服务器上调用操作方法来验证客户端上的输入。
[Required] [Range]
public class Student
{
[Required]
[Range(1,10,ErrorMessage = "id 为 1-10 之间的数字")]
public int Id { get; set; }
public string Name { get; set; }
}
ModelState
[HttpPost]
[Route("option/body")]
public IActionResult CreateOption([FromBody] Student student)
{
if (!ModelState.IsValid)
{
return ValidationProblem();
}
return Ok(student);
}
FluentValidation
不同场景下同一个模型有不同的验证规则,最好将模型与验证分开
表达式写法:
public class CustomerValidator : AbstractValidator<Customer> {
public CustomerValidator() {
RuleFor(x => x.Surname).NotEmpty();
RuleFor(x => x.Forename).NotEmpty().WithMessage("Please specify a first name");
RuleFor(x => x.Discount).NotEqual(0).When(x => x.HasDiscount);
RuleFor(x => x.Address).Length(20, 250);
RuleFor(x => x.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
}
private bool BeAValidPostcode(string postcode) {
// custom postcode validating logic goes here
}
}
Installation:https://docs.fluentvalidation.net/en/latest/installation.html
Install-Package FluentValidation
StudentValidator
namespace HelloApi.Validations
{
public class StudentValidator : AbstractValidator<Student>
{
public StudentValidator()
{
RuleFor(s => s.Id).InclusiveBetween(1,10).WithMessage("id需要在1和10之间");
}
}
}
ASP.NET Core Getting Started:https://docs.fluentvalidation.net/en/latest/aspnet.html
dotnet add package FluentValidation.AspNetCore
ConfigureServices
单个添加
services.AddControllers()
.AddFluentValidation();
// 通过依赖注入的方式(单个添加)
services.AddTransient<IValidator<Student>, StudentValidator>();
全部添加
// 通过扫描程序集的方式(全部添加)
services.AddControllers()
.AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<StudentValidator>());
返回数据处理
- 返回数据类型
- 格式化响应数据
返回数据类型
ASP.NET Core Web API 中控制器操作的返回类型:https://docs.microsoft.com/zh-cn/aspnet/core/web-api/action-return-types?view=aspnetcore-5.0
- 特定类型
- IActionResult
- ActionResult
特定类型:最简单的操作返回基元或复杂数据类型(如 string 或自定义对象类型)
IActionResult:常见返回类型为 BadRequestResult (400)、NotFoundResult (404) 和 OkObjectResult (200)
[HttpPost]
[Route("option/body")]
public IActionResult CreateOption([FromBody] Student student)
{
if (!ModelState.IsValid)
{
return ValidationProblem();
}
//return BadRequest();
//return NotFound();
return Ok(student);
}
格式化响应数据
设置 ASP.NET Core Web API 中响应数据的格式:https://docs.microsoft.com/zh-cn/aspnet/core/web-api/advanced/formatting?view=aspnetcore-5.0
浏览器和内容协商
services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;// 浏览器和内容协商
});
添加 XML 格式支持
services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true; // 浏览器和内容协商
})
.AddXmlSerializerFormatters() // 添加 XML 格式支持
.AddFluentValidation();
启动程序,添加 XML Headers 访问:

添加基于 Newtonsoft.Json 的 JSON 格式支持
添加 nuget 包:Microsoft.AspNetCore.Mvc.NewtonsoftJson
services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true; // 浏览器和内容协商
})
.AddNewtonsoftJson()// 添加基于 Newtonsoft.Json 的 JSON 格式支持
.AddXmlSerializerFormatters() // 添加 XML 格式支持
.AddFluentValidation();
GitHub源码链接:
https://github.com/MingsonZheng/ArchitectTrainingCamp/tree/main/HelloApi
课程链接
https://appsqsyiqlk5791.h5.xiaoeknow.com/v1/course/video/v_5f39bdb8e4b01187873136cf?type=2

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。
如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。
.NET 云原生架构师训练营(模块二 基础巩固 MVC终结点)--学习笔记的更多相关文章
- .NET 云原生架构师训练营(设计原则与模式)--学习笔记
在复杂系统的架构设计中引入设计原则与模式,能够极大降低复杂系统开发.和维护的成本 目录 几个问题 为什么要学习设计模式 优良架构设计的具体指标 理解复杂系统 面向对象思想(指导复杂系统的分析.设计.实 ...
- .NET 云原生架构师训练营(权限系统 代码重构)--学习笔记
目录 模块拆分 代码重构 模块拆分 代码重构 AuthenticationController PermissionController IAuthorizationMiddlewareResultH ...
- .NET 云原生架构师训练营(KestrelServer源码分析)--学习笔记
目录 目标 源码 目标 理解 KestrelServer 如何接收网络请求,网络请求如何转换成 http request context(C# 可识别) 源码 https://github.com/d ...
- .NET 云原生架构师训练营(模块一 架构师与云原生)--学习笔记
目录 什么是软件架构 软件架构的基本思路 单体向分布式演进.云原生.技术中台 1.1 什么是软件架构 1.1.1 什么是架构? Software architecture = {Elements, F ...
- .NET 云原生架构师训练营(建立系统观)--学习笔记
目录 目标 ASP .NET Core 什么是系统 什么是系统思维 系统分解 什么是复杂系统 作业 目标 通过整体定义去认识系统 通过分解去简化对系统的认识 ASP .NET Core ASP .NE ...
- .NET 云原生架构师训练营(权限系统 RGCA 架构设计)--学习笔记
目录 项目核心内容 实战目标 RGCA 四步架构法 项目核心内容 无代码埋点实现对所有 API Action 访问控制管理 对 EF Core 实体新增.删除.字段级读写控制管理 与 Identity ...
- .NET 云原生架构师训练营(模块二 基础巩固 敏捷开发)--学习笔记
2.7.1 敏捷开发 敏捷介绍 敏捷的起源 敏捷软件开发宣言 敏捷开发十二原则 生命周期对比 敏捷开发的特点 敏捷的发展 敏捷的核心 敏捷的起源 2001年,17个老头子在一起一边滑雪,一边讨论工作, ...
- .NET 云原生架构师训练营(模块二 基础巩固 MongoDB 介绍和基础)--学习笔记
2.5.1 MongoDB -- 介绍 mysql vs mongo 快速开始 mysql vs mongo 对比 mysql mongo 数据存储 table 二维表结构,需要预先定义结构 json ...
- .NET 云原生架构师训练营(模块二 基础巩固 MongoDB 问答系统)--学习笔记
2.5.6 MongoDB -- 问答系统 MongoDB 数据库设计 API 实现概述 MongoDB 数据库设计 设计优化 内嵌(mongo)还是引用(mysql) 数据一致性 范式:将数据分散到 ...
- .NET 云原生架构师训练营(模块二 基础巩固 Scrum 团队)--学习笔记
2.7.3 Scrum 团队 理想的环境 团队章程 如何组建 Scrum 团队 产品待办事项列表 用户故事 敏捷开发流程 理想的环境 5-9人 100% 跨职能 在一起 自组织 自组织 目标 授权 沟 ...
随机推荐
- 新手学习VUE——环境搭建及创建项目
第一种方式: 1. 下载安装node.js 检查是否成功:node-v或npm-v 2..搭建项目: 第一种方法:用iview脚手架建项目 打开iview官网==>生态 ===>i ...
- 全流程机器视觉工程开发(二)PaddleDetection:拉框,然后开始训练模型
前言 我现在在准备做一个全流程的机器视觉的工程,之前做了很多理论相关的工作.大概理解了机器视觉的原理,然后大概了解了一下,我发现现在的库其实已经很发展了,完全不需要用到非常多的理论,只需要知道开发过程 ...
- NOIP2020游记——AFO之战
阅读时请播放此音乐,这是我精心挑选的,很适合本文. Day-0奇遇 考试前一天,不顺,很不顺,简直可以写小说了.(不想看我车店可以往下翻,Day-1在后边) 我是下午两点从齐齐哈尔出发前往省会哈尔滨的 ...
- HP笔记本(Inspiron 7472) 视频时无摄像头的处理方案
需要视频考试的前一天,测试摄像头时发现微信视频时竟然摄像头打不开.比较焦急,尝试了好几种办法,并在2小时内找出解决方案. 一.查看设备是否被禁用 我的电脑->右键->设备管理器-> ...
- JQuery - CheckBox Prop 和 attr 的区别
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 百度网盘(百度云)SVIP超级会员共享账号每日更新(2024.01.03)
一.百度网盘SVIP超级会员共享账号 可能很多人不懂这个共享账号是什么意思,小编在这里给大家做一下解答. 我们多知道百度网盘很大的用处就是类似U盘,不同的人把文件上传到百度网盘,别人可以直接下载,避免 ...
- 【scikit-learn基础】--『回归模型评估』之偏差分析
模型评估在统计学和机器学习中具有至关重要,它帮助我们主要目标是量化模型预测新数据的能力. 本篇主要介绍模型评估时,如何利用scikit-learn帮助我们快速进行各种偏差的分析. 1. **R² ** ...
- k8s~istio的安装与核心组件
安装istio 在线安装:https://istio.io/latest/docs/setup/getting-started/#download 或者直接在这里下载:https://github.c ...
- [转帖]OS、PFS、DFS 有啥区别?一文搞懂 6 大临床试验终点
https://oncol.dxy.cn/article/670607 说到肿瘤临床研究,就不得不说临床试验终点(End Point),比如大家熟知的 OS.PFS.ORR 还有 DFS.TTP.TT ...
- [转帖]【sql server安全】sql server连接加密,sql server SSL加密连接
https://www.cnblogs.com/gered/p/13595098.html#_label1_0 MSSQL - 最佳实践 - 使用SSL加密连接 回到顶部 author: 风移 回到顶 ...