前言

相信一直关注我的园友都知道,我写的博文都没有特别枯燥理论性的东西,主要是当每开启一门新的技术之旅时,刚开始就直接去看底层实现原理,第一会感觉索然无味,第二也不明白到底为何要这样做,所以只有当你用到了,你再去看理论性的文章时才会豁然开朗,这是我一直以来学习技术的方法。本文我们来讲解.NET Core中的模型绑定。

话题

在ASP.NET Core之前MVC和Web APi被分开,也就说其请求管道是独立的,而在ASP.NET Core中,WebAPi和MVC的请求管道被合并在一起,当我们建立控制器时此时只有一个Controller的基类而不再是Controller和APiController。所以才有本节的话题在模型绑定上呈现出有何不同呢?下面我们一起来看看。

ASP.NET MVC模型绑定

我们首先还是老规矩给出测试类

    public class Person
{
public string Name { get; set; }
public string Address { get; set; }
public int Age { get; set; }
}

接着POST请求通过Action方法进行模型绑定。

        [HttpPost]
public JsonResult PostPerson(Person p)
{
return Json(p);
}

到这里,后台就大概over了,是不是就这么完了呢,我们一直在强调模型绑定这个词语,那么到底什么是模型绑定呢,有必要解释下。我们PostPerson这个方法中有一个Person的变量参数,那么问题来了,前台发出请求到这个方法从而该参数接收到传递过来的数据从而进行响应,这个p到底是怎么接收到的呢,恩,通过模型绑定呗,为了将数据聚合到对象或者其他简单的参数可以通过模型绑定来查找数据,常见的绑定方式有如下四种。

路由值(Route Values):通过导航到路由如{controller}/{action}/{id}此时将绑定到id参数。

查询字符串(QueryStrings):通过查询字符串中的参数来绑定,如name=Jeffcky&id=1,此时name和id将进行绑定。

请求Body(Body):通过在POST请求中将数据传入到Body中此时将绑定如上述Person对象中。

请求Header(Header):绑定数据到Http中的请求头中,这种相对来说比较少见。

所以通过上述讲述我们知道有多种方式将数据从客户端传递到服务端,然后模型绑定会自动为我们创建正确的方法来绑定到后台参数中,简单和复杂的类型参数都会进行绑定。

接下来我们来演示在ASP.NET MVC中绑定的方式。此时只需给出前台页面了。

      <form id="form">
<div class="form-group">
<div class="control-label col-md-2">名称:</div>
<div class="col-md-10">
<input name="Name" id="Name" class="form-control" />
</div>
</div>
<div class="form-group">
<div class="control-label col-md-2">年龄:</div>
<div class="col-md-10">
<input name="Age" id="Age" class="form-control" />
</div>
</div>
<div class="form-group">
<div class="control-label col-md-2">家乡地址:</div>
<div class="col-md-10">
<input name="Address" id="Address" class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="button" id="btnForm" value="MVC提交表单" class="btn btn-success" />
<input type="button" id="btnJson" value="WebAPi提交" class="btn btn-warning" />
</div>
</div>
</form>

首先我们提交表单形式来传输数据。

           $("#btnForm").on("click", function () {
var dataform = $('form').serialize();
$.ajax({
url: "../MVC/PostPerson",
contentType: "application/x-www-form-urlencoded;charset=utf-8",
dataType: "json",
type: "post",
data: dataform,
success: function (data) {
console.log(data);
}
});
});

然后我们通过传输JSON的数据同样来发出POST请求。

             $("#btnForm").on("click", function () {
$.ajax({
url: "../MVC/PostPerson",
contentType: "application/json;charset=utf-8",
dataType: "json",
type: "post",
data: JSON.stringify(datajson),
success: function (data) {
console.log(data);
}
});
});

结果同样返回上述数据,就不再演示,下面我们看看WebAPi中的情况。

ASP.NET WebAPi模型绑定

当然上述利用JSON传输数据同样也适用于WebAPi,下面我们来看看利用查询字符串在WebAPi中的情况。

           $("#btnJson").on("click", function () {
var dataform = $('form').serialize();
console.log(dataform);
$.ajax({
url: "../api/WebAPi/PostPerson",
contentType: "application/x-www-form-urlencoded;charset=utf-8",
dataType: "json",
type: "post",
data: dataform,
success: function (data) {
console.log(data);
}
});
});

我们再来看看在WebAPi中表单的形式。

             $("#btnJson").on("click", function () {
var datajson = { Name: "Jeffcky", Age: 24, Address: "湖南省" };
console.log(datajson);
$.ajax({
url: "../api/WebAPi/PostPerson",
contentType: "application/x-www-form-urlencoded;charset=utf-8",
dataType: "json",
type: "post",
data: datajson,
success: function (data) {
console.log(data);
}
});
});

上述我们看到在ASP.NET MVC/WebAPi中无论是以表单POST的形式抑或JSON的形式控制器具有绑定都Http请求Body的能力同时数据都会返回给我们,我们不需要做出任何特别的说明,所以都没毛病。接下来我们来看看ASP.NET Core MVC/WebAPi中的模型绑定形式。

ASP.NET Core MVC/WebAPi

在ASP.NET Core中为了加载服务器的静态文件如css、js、文件等等记住需要在Startup.cs中的Configure方法下添加如下一句来启用静态文件:

 app.UseStaticFiles();

由于在ASP.NET Core中MVC和WebAPi请求管道合并,所以只有Controller基类,我们在控制器下建立如下方法:

   [Route("[controller]")]
public class HomeController : Controller
{
[HttpGet("Index")]
public IActionResult Index()
{
return View();
} [HttpPost("PostPerson")]
public IActionResult PostPerson(Person p)
{
return Json(p);
}
}

此时加载页面如下:

接下来我们分别演示以表单形式和JSON形式来发出POST请求。

        $(function () {
$("#btn").on("click", function () {
var dataform = $('form').serialize();
console.log(dataform);
$.ajax({
url: "../Home/PostPerson",
contentType: "application/x-www-form-urlencoded;charset=utf-8",
dataType: "json",
type: "post",
data: dataform,
success: function (data) {
console.log(data);
}
});
});
});

接下来我们再来看看传输JSON。

        var datajson = { Name: "Jeffcky", Age: , Address: "湖南省" };
$(function () {
$("#btn").on("click", function () {
console.log(datajson);
$.ajax({
url: "../Home/PostPerson",
contentType: "application/json;charset=utf-8",
dataType: "json",
type: "post",
data: JSON.stringify(datajson),
success: function (data) {
console.log(data);
}
});
});
});

此时就和ASP.NET MVC/WebAPi中情况就不一样,此时后台接收不到数据,从而返回null。在ASP.NET Core中为了正确绑定到JSON我们需要在Action方法中对参数显式指定[FromBody]。

        [HttpPost("PostPerson")]
public IActionResult PostPerson([FromBody]Person p)
{
return Json(p);
}

通过使用[FromBody]则能正常使用了,那么到了这里你是不是就认为我们应该总是使用[FromBody]特性呢,如果你这样想就大错特错了,我们将上述contentType修改成表单形式

 contentType: "application/x-www-form-urlencoded;charset=utf-8",

此时会得到415不支持此媒体类型,当我们使用[FromBody]特性时,也就是明确告诉.NET Core要使用请求中的contentType头来决定输入参数对于模型绑定。默认情况下在我们注入MVC服务时被配置使用的时JsonInputFormatter,当然我们可以配置其他formatter比如xml,所以在这里我们将绑定到请求的Body中,但是输入参数不对,因为其格式为Name=Jeffcky&Age=24&Address=湖南省,所以会出现不支持该媒体类型,在这里我们要么去除[FromBody]特性,要么添加[FromForm]特性。如果我们既需要绑定表单也需要绑定JSON该如何是好呢?我们只能写两个方法。如下:

        [HttpPost("PostFormPerson")]
public IActionResult PostFormPerson(Person p)
{
return Json(p);
} [HttpPost("PostJsonPerson")]
public IActionResult PostJsonPerson([FromBody] Person p)
{
return Json(p);
}

现在看来想想是不是没有之前ASP.NET MVC/WebAPi灵活和方便呢,微软是不是闲的蛋疼啊,所以我们是不是觉得虽然是两个方法我们将其路由定义成相同的,那么当我们在调用时让其自己去匹配不就得了,于是乎就有了如下的情况。

        [HttpPost("PostPerson")]
public IActionResult PostFormPerson(Person p)
{
return Json(p);
} [HttpPost("PostPerson")]
public IActionResult PostJsonPerson([FromBody] Person p)
{
return Json(p);
}

此时还没到控制器下的路由方法就已经发生500错误了,如下:

好了看到这里我们本节的内容就已经接近尾声了,是不是觉得微软闲的没事干了,明明一个方法就可以ok的事,非得要我们写两个方法,原因到底是什么呢,据了解社区是为了安全考虑,主要原因是为了防止CSRF(Cross-Site Rquest Forgery)究竟内部到底是怎么防止CSRF的呢,不得而知,难道像之前MVC中的For...那样么,不得而知。

总结

本节我们比较详细的讨论了ASP.NET Core MVC/WebAPi中的模型绑定,如果在前台是JSON绑定,在ASP.NET Core MVC/WebAPi必须要用[FromBody]明确标识,否则你懂的。

转自:https://www.cnblogs.com/CreateMyself/p/6246977.html

【转】ASP.NET Core MVC/WebAPi 模型绑定探索的更多相关文章

  1. ASP.NET Core MVC/WebAPi 模型绑定探索

    前言 相信一直关注我的园友都知道,我写的博文都没有特别枯燥理论性的东西,主要是当每开启一门新的技术之旅时,刚开始就直接去看底层实现原理,第一会感觉索然无味,第二也不明白到底为何要这样做,所以只有当你用 ...

  2. ASP.NET Core MVC/WebAPi 模型绑定探索 转载https://www.cnblogs.com/CreateMyself/p/6246977.html

    前言 相信一直关注我的园友都知道,我写的博文都没有特别枯燥理论性的东西,主要是当每开启一门新的技术之旅时,刚开始就直接去看底层实现原理,第一会感觉索然无味,第二也不明白到底为何要这样做,所以只有当你用 ...

  3. ASP.NET Core MVC/WebAPi 模型绑定

    public class Person { public string Name { get; set; } public string Address { get; set; } public in ...

  4. ASP.NET Core MVC/WebAPi如何构建路由?

    前言 本节我们来讲讲ASP.NET Core中的路由,在讲路由之前我们首先回顾下之前所讲在ASP.NET Core中的模型绑定这其中有一个问题是我在项目当中遇见的,我们下面首先来看看这个问题. 回顾A ...

  5. ASP.NET Core 中的模型绑定

    微软官方文档:ASP.NET Core 中的模型绑定 Route 是通过MVC Route URL取值. 如:http://localhost:5000/Home/Index/2,id取出的值就会是2 ...

  6. 你所不知道的ASP.NET Core MVC/WebApi基础系列(二)

    前言 好久没冒泡了,算起来估计有快半年没更新博客了,估计是我第一次停更如此之久,人总有懒惰的时候,时间越长越懒惰,但是呢,不学又不行,持续的惰性是不行dei,要不然会被时光所抛弃,技术所淘汰,好吧,进 ...

  7. 你所不知道的ASP.NET Core MVC/WebApi基础系列 (二)

    转自博客:https://www.cnblogs.com/CreateMyself/p/10604293.html 前言 本节内容,我们来讲讲.NET Core当中的模型绑定系统.模型绑定原理.自定义 ...

  8. ASP.NET Core MVC 之模型(Model)

    1.模型绑定 ASP.NET Core MVC 中的模型绑定将数据从HTTP请求映射到操作方法参数.参数既可以是简单类型,也可以是复杂类型.MVC 通过抽象绑定解决了这个问题. 2.使用模型绑定 当 ...

  9. 你所不知道的ASP.NET Core MVC/WebApi基础系列(一)

    前言 最近发表的EF Core貌似有点多,可别误以为我只专攻EF Core哦,私下有时间也是一直在看ASP.NET Core的内容,所以后续会穿插讲EF Core和ASP.NET Core,别认为你会 ...

随机推荐

  1. div背景图片自适应

    对背景图片设置属性:background-size:cover;可以实现背景图片适应div的大小. background-size有3个属性: auto:当使用该属性的时候,背景图片将保持100% 的 ...

  2. mysql将一个表拆分成多个表(一)(转载)

    转载 直接根据数据量进行拆分 有一个5000条数据的表,要把它变成没1000条数据一个表的5等份. 假设:表名:xuesi 主键:kidxuesi共有5000条数据,kid从1到5000自动增长题目: ...

  3. 2020-2-18 restful的学习

    1-1 restful简介及资源的介绍 restful   是什么? 本质:一种软件架构风格 核心:面向资源     解决的问题: 1. 降低开发的复杂性 2. 提高系统的可伸缩性     设计概念和 ...

  4. Laplacian Mesh Editing 拉普拉斯形变(待回学校更新)

    前言 因为实验需要用到拉普拉斯形变,但找了好久找到一个非常适合入门的资料.再此记录下我的学习过程,也算搬运翻译过来. Introduction / Basic Laplacian Mesh Repre ...

  5. token和session的区别

    session和token都是用来保持会话,功能相同 一.session机制,原理 session是服务端存储的一个对象,主要用来存储所有访问过该服务端的客户端的用户信息(也可以存储其他信息),从而实 ...

  6. 第1节 storm编程:7、并行度分析以及如何解决线程安全问题

    storm其实就是一个多进程与多线程的框架 开多个进程:分配到的资源更多 开多个线程:执行的速度更快 设置进程个数以及线程个数 ==================================== ...

  7. JavaWeb开发:从购买服务器到简单demo运行

    写这篇文章的目的: 一个是为了记录实施过程,方便自己日后查阅: 另一个是给项目组成员提供一个参考,方便他们以后搭建自己的项目环境: 当然若能帮助到更多的朋友,那就再好不过了:D 需要注意: 我本身也是 ...

  8. Verilog有符号整型数(signed int)比大小

    本文参考了https://blog.csdn.net/wenxinwukui234/article/details/42119265/ 关于2进制补码的思考和讨论. ================= ...

  9. windows目标进程注入dll

    在别的程序注入dll 步骤: ,获取目标进程ID,CreateToolhelp32Snapshot()函数; ,获取目标进程句柄,OpenProcess()函数; ,目标进程要一块内存,Virtual ...

  10. MySQL设置各类字符集

    一.查看字符集编码: 登录mysql show variables like '%character%'; 二.修改编码: 编辑/etc/my.cnf ,设置后的配置文件如下: [root@node0 ...