在前面的几篇文章中我们都是采用在URI中元数据类型进行传参,实际上ASP.NET Web API也提供了对URI进行复杂参数的绑定方式--Model绑定。这里的Model可以简单的理解为目标Anction方法的某个参数。

eg:

public Figure GetFigureFromQueryString([ModelBinder]Figure figure)

{

return figure;

}

请求url: http://localhost:4044/api/Figure/GetFigureFromQueryString?FirstName=Bran&LastName=Stack

结果:

{

"FirstName": "Bran",

"LastName": "Stack"

}

(本篇为了更好的体现绑定结果,所有Anction的返回结果都是请求参数或整合的后的请求参数)

ModelBinder

在之前的文章中多次提到URI的数据主要来源于两种方式:Route,QueryString。但是URI只提供简单的基础数据类型,在上面的例中,我们会发现参数变成了类。ModelBinderAttribute提供了基础数据类型向复杂类型数据转换的功能。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]

public class ModelBinderAttribute : ParameterBindingAttribute

{

}

从定义中我们可以看出ModelBinder的AttributeUsage可以看出来ModelBinder可以用于类型与参数。下面我就列举一些Model绑定的形式。

  1. 简单类

这里所说的简单类是指数据是指类的公开属性是基础数据类型。比如我们之前一直使用的Figure类。

public class Figure

{

public string FirstName { get; set; }

public string LastName { get; set; }

}

还是以本文开始的GetFigureFromQueryString([ModelBinder]Figure figure) 为例。因为该Action中只采用了一个参数。所以在传参的过程中只需要将FirstName,LastName作为QueryString传递,ModelBinder将转换出Figure对象。

http://localhost:4044/api/Figure/GetFigureFromQueryString?FirstName=Bran&LastName=Stack

同时我们也可以采用route形式进行传参:

[Route("GetFigureFromRoute/{FirstName}/{LastName}")]

public Figure GetFigureFromRoute(Figure figure)

url:

http://localhost:4044/api/Figure/GetFigureFromRoute/Bran/Stack

当然以此类推也也可以进行混合的传参:

还是基于 GetFigureFromRoute Action

我们用以下url进行访问:

http://localhost:4044/api/Figure/GetFigureFromRoute/Bran/Stack?FirstName=Robb

那我们得到的结果将是:

{

"FirstName": "Robb",

"LastName": "Stack"

}

由此可以看出

QueryString参数的优先级是高于Route参数的

2.多参数(简单类)

第一种情况我们是考虑了一个参数,现在我们把参数变成两个,如下:

List<Figure> 方法名 (Figure a, Figure b)

因为这个时候出现了两个类型相同的参数,仅靠属性名已经不能对参数进行区别。这个时候WebAPI为我们提供了前缀形式对参数进行区分。下面就以Route的方式做一demo:、

[Route("GetTwoFigureFromRoute/{a.FirstName}/{a.LastName}/{b.FirstName}/{b.LastName}")]

public List<Figure> GetTwoFigureFromRoute(Figure a, Figure b)

我们对路由进行一个简单分析:即{参数名}.{属性名} 作为路由的key

{a.FirstName}:参数a的FirstName属性

{a.LastName}:参数a的LastName属性

{b.FirstName}:参数b的FirstName属性

{b.LastName}:参数b的LastName属性

用以下url访问

http://localhost:4044/api/Figure/GetTwoFigureFromRoute/Bran/Stack/Robb/Stack

得到的结果就是:

[

{

"FirstName": "Bran",

"LastName": "Stack"

},

{

"FirstName": "Robb",

"LastName": "Stack"

}

]

对于QueryString形式传参也非常简单,直接将{参数名}.{属性名} 作为QueryString的key.比如:

public List<Figure> GetTwoFigureFromQueryString(Figure a, Figure b)

url:

http://localhost:4044/api/Figure/GetTwoFigureFromQueryString?a.FirstName=Bran&a.LastName=Stack&b.FirstName=Robb&b.LastName=Stack

将得到如Route形式一样的结果

3.复杂类

现在我们对Figure添加一个Direwolf类的属性Direwolf,让其变为一个复杂类

public class Figure

{

public Direwolf Direwolf { get; set; }

}

public class Direwolf

{

public string Name { get; set; }

public string Color { get; set; }

}

在传参数的过程中显然我们不能对直接对Direwolf属性赋值,所以我们要对Direwolf属性进行拆分,这个时候我也要用到前缀的方式进行传参。如下:

public Figure GetComplexFigureFromQueryString(Figure figure)

url:

http://localhost:4044/api/Figure/GetComplexFigureFromQueryString?FirstName=Jon&LastName=Snow&Direwolf.Color=White&Direwolf.Name=Summer

结果:

{

"FirstName": "Bran",

"LastName": "Stack",

"Direwolf": {

"Name": "Summer",

"Color": "White"

}

}

对于Route形式也是一样:

[Route("GetComplexFigureFromRoute/{FirstName}/{LastName}/{Direwolf.Name}/{Direwolf.Color}")]

public Figure GetComplexFigureFromRoute(Figure figure)

url:

http://localhost:4044/api/Figure/GetComplexFigureFromRoute/Bran/Stack/Grey/Summer

对于多参数的形式也照样可以处理:

public List<Figure> GetTwoComplexFigureFromQueryString(Figure a, Figure b)

url:

http://localhost:4044/api/Figure/GetTwoComplexFigureFromQueryString?a.FirstName=Bran&a.LastName=Stack&a.Direwolf.Color=Grey&a.Direwolf.Name=Summer&b.FirstName=Jon&b.LastName=Snow&b.Direwolf.Color=White&b.Direwolf.Name=Ghost

4.集合类型

集合类型因为存在长度的确定性,所以还是需要通过前缀的方式去指定序列号,如下:

public List<int> GetList([ModelBinder] List<int> list)

{

return list;

}

url:

http://localhost:4044/api/Figure/GetList?[0]=0&[1]=1&[2]=2&[3]=3

结果:

[

0,

1,

2,

3

]

注意

序列号必须是从0开始连续的整数,不然就只能得到序列号断裂之前的数据,如:

url:

http://localhost:4044/api/Figure/GetList?[0]=0&[2]=1&[2]=2&[3]=3

结果:

[

0

]

另外,如果要采用Route形式的传参方式,就必须考虑数据的长度问题。

5字典类型

WebAPI在数据字典类型的先将数据转化成KeyValuePair的集合类型,再转化成字典类型。所以再传参的时候我们可以采用与集合类型一致的方式。如:

public Dictionary<string, int> GetDictionary([ModelBinder]Dictionary<string, int> dic)

url:

http://localhost:4044/api/Figure/GetDictionary?[0].Key=a&[0].Value=1&[1].Key=b&[1].Value=2

结果

{

"a": 1,

"b": 2

}

源码

Github: https://github.com/BarlowDu/WebAPI (API_4)

ASP.NET WebAPI 04 Model绑定的更多相关文章

  1. ASP.NET WebAPI 05 参数绑定

    ParameterBindingAttribute 在上一篇中重点讲了ModelBinderAttribute的使用场景.这一篇详细的讲一下ModelBinder背后的参数绑定原理. ModelBin ...

  2. ModelBinder——ASP.NET MVC Model绑定的核心

    ModelBinder——ASP.NET MVC Model绑定的核心 Model的绑定体现在从当前请求提取相应的数据绑定到目标Action方法的参数.通过前面的介绍我们知道Action方法的参数通过 ...

  3. ASP.NET MVC Model绑定(六)

    ASP.NET MVC Model绑定(六) 前言 前面的篇幅对于IValueProvider的使用做个基础的示例讲解,但是没并没有对 IValueProvider类型的实现做详细的介绍,然而MVC框 ...

  4. ASP.NET MVC Model绑定(五)

    ASP.NET MVC Model绑定(五) 前言 前面的篇幅对于IValueProvider的获取位置和所处的生成过程做了讲解,本篇将会对IValueProvider的使用做个基础的示例讲解,读完本 ...

  5. ASP.NET MVC Model绑定(四)

    ASP.NET MVC Model绑定(四) 前言 前面的篇幅对于Model绑定器IModelBinder以及实现类型.Model绑定器提供程序都作了粗略的讲解,可以把Model绑定器想象成一个大的容 ...

  6. ASP.NET MVC Model绑定(三)

    ASP.NET MVC Model绑定(三) 前言 看过前两篇的朋友想必对Model绑定有个大概的了解,然而MVC框架给我们提供了更高的可扩展性的提供程序编程模式,也就是本篇的主题了,会讲解一下Mod ...

  7. ASP.NET MVC Model绑定(二)

    ASP.NET MVC Model绑定(二) 前言 上篇对于Model绑定的简单演示想必大家对Model绑定的使用方式有一点的了解,那大家有没有想过Model绑定器是在什么时候执行的?又或是执行的过程 ...

  8. ASP.NET MVC Model绑定(一)

    ASP.NET MVC Model绑定(一) 前言 ModelMetadata系列的结束了,从本篇开始就进入Model绑定部分了,这个系列阅读过后你会对Model绑定有个比较清楚的了解, 本篇对于Mo ...

  9. Asp.net MVC中提交集合对象,实现Model绑定

    Asp.net MVC中的Model自动绑定功能,方便了我们对于request中的数据的处理, 从客户端的请求数据,自动地以Action方法参数的形式呈现.有时候我们的Action方法中想要接收数组类 ...

随机推荐

  1. P3355 骑士共存问题

    P3355 骑士共存问题 题目描述 在一个 n*n (n <= 200)个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入 对于给定的 n*n ...

  2. gitlab的备份与恢复与迁移

    一.gitlab的备份1.1 创建备份目录,并授权 1 2 3 4 [root@linux-node1 ~]# mkdir /data/backups/gitlab -p [root@linux-no ...

  3. UITableViewCell在非Nib及Cell重用下设置CellStyle

    在UITableViewController(实现了UITableViewDataSource)下需要实现 - (UITableViewCell *)tableView:(UITableView *) ...

  4. VsCode搭建Java开发环境(Spring Boot项目创建、运行、调试)

    源码地址:https://github.com/YANGKANG01/Spring-Boot-Demo 安装扩展 安装如下两个主要扩展即可,这两个扩展已关联java项目开发主要使用的maven.spr ...

  5. bzoj千题计划170:bzoj1968: [Ahoi2005]COMMON 约数研究

    http://www.lydsy.com/JudgeOnline/problem.php?id=1968 换个角度 一个数可以成为几个数的约数 #include<cstdio> #incl ...

  6. 动态规划:树形DP-景点中心(树的带权重心)

    话说宁波市的中小学生在镇海中学参加计算机程序设计比赛,比赛之余,他们在镇海中学的各个景点参观.镇海中学共有n个景点,每个景点均有若干学生正在参 观.这n个景点以自然数1至n编号,每两个景点的编号均不同 ...

  7. virtual Box在Centos 7上的安装

    1.首先,我们需要在oracle官网下载virtual Box的centos7版本: 下载地址为:http://download.virtualbox.org/virtualbox/5.0.12/Vi ...

  8. 【转】C# Graphics类详解

    Brush 类 .NET Framework 4 定义用于填充图形形状(如矩形.椭圆.饼形.多边形和封闭路径)的内部的对象. 属于命名空间:  System.Drawing 这是一个抽象基类,不能进行 ...

  9. Spring4笔记3--Bean的装配

    Bean的装配: Bean 的装配,即 Bean 对象的创建.容器根据代码要求创建 Bean 对象后再传递给代码的过程,称为 Bean 的装配. 1. 创建Bean对象的方式: 1. 通过 getBe ...

  10. Django 1.10中文文档-模型参考

    模型字段 本文档包含了Django提供的全部模型 Field 包括 字段选项 和 字段类型 的API参考. 参见 如果内建的字段不能满足你的需求, 你可以蚕食 django-localflavor ( ...