ASP.NET核心MVC模型绑定的用法和原理
https://www . cn blogs.com/savorboard/p/aspnetcore-model binding . html
前言
我查询了MVC中的模型绑定,主要是如何使用,以及模型绑定过程中的一些用法和概念。很少有关于模型绑定内部机制实现的文章。本文将解释如何在ASP.NET核心MVC中实现模型绑定以及它的一些其他用途。
模型绑定的用途
通常我们在使用MVC框架的时候,不需要关注模型绑定的相关功能,因为它是集成到MVC框架中的。当我们在浏览器中访问一个地址时,无论是GET还是POST访问,MVC框架在映射到Action的过程中都有自动绑定的对象或路由参数,这就是我们使用的模型绑定。
在ASP.NET核心MVC中,模型绑定分为简单模型绑定和复杂模型绑定。简单的模型绑定,比如直接从表单或者URL路由数据中获取inFormation,然后应用到Action方法的每个参数中,如果是复杂的模型绑定,可能不会简单地转换为参数的值,还可能涉及到一些数据类型转换、模型分解、参数验证等。
让我们看一个模型绑定的例子:
假设我们有一个名为Person的ViewModel对象,其代码如下:
公共类人员
{
公共字符串名称{ get设置;}
public int Age { get设置;}
}
在这个视图模型对象中,使用了一些非常简单的类型,因此我们的操作定义如下:
公共类人员控制器
{
[HttpSet]
[路线(' ~ API/人员/添加')]
公共机构结果创建人(人员)
{
返回Ok(人);
}
}
在上面的代码中,我们可以向http://localhost :5000/API/Person/add的地址发送POST请求。身体类型使用普通的形式,参数使用上面的人定义的姓名、年龄和年龄。给Action添加一个断点,我们可以看到person变量中的值,然后Action会返回一个json序列化的结果对象。
这样的过程是模型绑定在实际开发中的目的和用途。
看起来简单吗?但是在内部模型中,绑定子系统是复杂的,由许多部分组成。
模型绑定的一些用法
在ASP.NET核心MVC中,支持以下表单类型的模型绑定。
[FromHeader],[FromQuery],[FromRoute],[FromForm]
示例:
公共机构结果创建人([FromForm]Person)
{
返回Ok(人);
}
这些[FromXXX]告诉模型绑定在解析期间从HttpContext的哪个部分获取信息。
一些模型绑定框架中定义的一些属性被用来限制或忽略模型建模过程中的一些参数。例如
[BindRequired],[BindNever]
这两个是模型绑定过程中增加的一些约束。BindRequired可以应用于类或属性,以限制绑定过程中必须需要的一些值。BindNever用于忽略当前参数的绑定。
还有两个【来自服务】和【来自身体】。
[FromServices]是参数绑定的过程,它告诉模型绑定框架参数是从DI容器中获取的。
[FromBody]是参数绑定的过程,它告诉框架使用配置的格式化程序从Http Body解析参数。
在[FromBody]中,默认使用MVC框。
架内部配置的 JsonInputFormatter 进行反序列化解析,如果你传递的 Body 中的类型是 application/xml,你可以在 ConfigureServices 方法中配置services.AddMvc().AddXmlSerializerFormatters();
进行XML的反序列化。
还有一个[ModelBinder]
这个可能很多人没用过,这个是应用在 Controller 中的属性上的,用来绑定属性信息。比如
public class Controller
{
[ModelBinder]
public string Name { get; set;}
public IActionResult CreatePerson(Person person)
{
return Ok(person);
}
}
在 Action 激活的时候,Controller 的 Name 属性也会具有Action 参数中 person 变量中名字和 Name 相同参数的值。
自定义模型绑定
自定义模型绑定属于 MVC 模型绑定的一些高级知识,在一些特殊情况中我们可能会使用到他们。 详情可以参考这篇 文章https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding,本文不打算做过多介绍。
MVC 模型绑定(ModelBinding)实现原理
看过我ASP.NET Core MVC Action 激活这篇文章的同学应该知道,在 Action 激活的过程中会涉及到很多状态,那么模型绑定是在ActionBegin
这个状态中进行的,同时在ActionNext
过程中被使用,我就直接接着这篇文章的 Action 执行部分进行讲解了。
首先,模型绑定的入口位于ControllerActionInvoker
这个类中的一个Next方法里
private Task Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted){
......
switch (next)
{
case State.ActionBegin:
BindArgumentsAsync();
goto case State.ActionNext;
case State.ActionNext:
_actionExecutingContext = new ActionExecutingContext(_arguments);
}
......
}
可以看到在State.ActionBegin
这个过程中使用了BindArgumentsAsync()
进行参数绑定,那么整个绑定过程就由此开始。
在 Core MVC 框架模型绑定部分源码中,模型绑定源码分为这几部分:元数据(Metadata),值提供器(ValueProvider),验证者(Validator),绑定器(Binder)。
元数据:元数据相当于模型绑定中的实体对象,用来储存在整个模型绑定子系统中需要的各种必要信息和元数据信息,包括模型参数的元数据和以及绑定信息的元数据等等。
值提供器:值提供器用来提供在运行时模型绑定器可以从中提取值的一个Provider, 默认情况下,值提供器会从以下地方提取各种资源的值:
1、以前绑定的操作参数(当该操作为子操作时)
2、表单字段 (FormValueProvider)
3、路由数据 (RouteValueProvider)
4、查询字符串参数 (QueryStringValueProvider)
5、JQuery 表单数据(JQueryFormValueProvider)
这些 ValueProvider 对象由CompositeValueProvider
进行统一管理,它是一个集合用来创建或者获取这些 ValueProvider 对象。
验证者:验证者是用来验证Action参数中模型字段的合法性。
它的默认实现是DefaultObjectValidator
,它会根据元数据信息来确定绑定过程中使用的具体 ValudatorProvider 对象,ValudatorProvider 是用来提供IModelValidator
接口实例对象的。
在 ASP.NET Core MVC 中有两个类实现了IModelValidator
接口,他们分别是DataAnnotationsModelValidator
和ValidatableObjectAdapter
。 其中ValidatableObjectAdapter
是一个适配器,用来转换和封装验证结果,所以我们主要看DataAnnotationsModelValidator
。
DataAnnotationsModelValidator
就是用来验证模型类中的各种 Attribute 的,也就是DataAnnotations
相关的那些类,比如[MaxLength]
,[Required]
,[RegularExpression]
等等。
绑定器: 绑定器用来绑定Action参数中的大多数简单和复杂的数据模型,它通过对模型各个属性使用递归逻辑来实现该目标。
针对不同类型的绑定具有不同的绑定器,如:
ArrayModelBinder
,SimpleTypeModelBinder
,FormFileModelBinder
,FormCollectionModelBinder
,ComplexTypeModelBinder
,BodyModelBinder
,HeaderModelBinder
,DictionaryModelBinder
,ServicesModelBinder
,KeyValuePairModelBinder
,ByteArrayModelBinder
,CancellationTokenModelBinder
,CollectionModelBinder
,BinderTypeModelBinder
这些 ModelBinder 对象都具有各自的 Provider 对象,对来返回当前Binder对象的实例对象。
这些 ModelBinder 对象由ParameterBinder
进行统一管理,ParameterBinder
对象会接收模型的元数据信息(Metadata),绑定器工厂(BinderFactory),验证者(Validator),然后进行最终的模型绑定流程,如下图:
回到总流程
我们回到ControllerActionInvoker
这个中,BindArgumentsCoreAsync
这个函数中会进行上层的模型绑定,流程如下:
以上总流程的前两步就是 MVC Core 模型绑定系统针对于 Controller 中 Action 参数的绑定,实际上除了针对 Action 参数绑定外,还会对 Controller 中的使用了[IModelBinder]
特性的进行绑定,那么第三步就是在做这个事情。
至此,模型绑定流程结束。
总结
在本篇中,我们学习了在 ASP.NET Core MVC 中模型绑定的一些用途和一些基本的用法,然后学习了 MVC框架中模型绑定的一些内部实现原理,通过这个学习我们可以对整个模型绑定系统更加的系统的一个了解,以便于我们有在工作系统的时候可以针对于模型绑定系统进行扩展。
如果你觉得本篇博客对你有帮助的话,感谢您的【推荐】。
如果你对 ASP.NET Core 有兴趣的话可以关注我,我会定期的在博客分享我的学习心得。
转https://www.cnblogs.com/savorboard/p/aspnetcore-modelbinding.html
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/79565.html