ASP.NET Core MVC/WebAPi 模型绑定探索-阿里云开发者社区

开发者社区> jeffcky> 正文

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

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

前言

相信一直关注我的园友都知道,我写的博文都没有特别枯燥理论性的东西,主要是当每开启一门新的技术之旅时,刚开始就直接去看底层实现原理,第一会感觉索然无味,第二也不明白到底为何要这样做,所以只有当你用到了,你再去看理论性的文章时才会豁然开朗,这是我一直以来学习技术的方法。本文我们来讲解.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: 24, 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]明确标识,否则你懂的。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
一句代码实现批量数据绑定“.NET技术”[下篇]
  《上篇》主要介绍如何通过DataBinder实现批量的数据绑定,以及如何解决常见的数据绑定问题,比如数据的格式化。接下来,我们主要来谈谈DataBinder的设计,看看它是如何做到将作为数据源实体的属性值绑定到界面对应的控件上的。
578 0
Asp.net MVC Fckeditor的扩展(支持PV3及自动绑定)
namespace System.Web.Mvc {     using System;     using System.Globalization;     ///      /// Fckeditor的HTMLHelper     /// http://chsword.
627 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4512 0
net MVC中的模型绑定、验证以及ModelState
net MVC中的模型绑定、验证以及ModelState 模型绑定 模型绑定应该很容易理解,就是传递过来的数据,创建对应的model并把数据赋予model的属性,这样model的字段就有值了。
1343 0
Spring MVC 使用POJO对象绑定请求参数值
index.jsp前台页面加上这些,把值输入之后,通过post提交到后台。 &lt;form action="springmvc/testPOJO" method="post"&gt; username: &lt;input type="text" name="username"/&gt; &lt;br/&gt; passwo
1605 0
SpringMVC自定义日期格式进行参数绑定
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.
536 0
重新想象 Windows 8 Store Apps (53) - 绑定: 与 ObservableCollection CollectionViewSource VirtualizedFilesVector VirtualizedItemsVector 绑定
原文:重新想象 Windows 8 Store Apps (53) - 绑定: 与 ObservableCollection CollectionViewSource VirtualizedFilesVector VirtualizedItemsVector 绑定 [源码下载] 重新想象 Wind...
691 0
+关注
jeffcky
耕耘博客、走进技术的世界!
173
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载