不同的方式传参
本文需要用到的自定义复杂类型:
public class Student
{
public int Age { get; set; }
public string Name { get; set; }
public string Color { get; set; }
}
query
传参
1.简单类型-简单类型
[HttpGet]
public ActionResult Get(string a, int b);
http://localhost:5000/api/values?a=aaa&b=111
2.简单类型-复杂类型
[HttpGet]
public ActionResult Get(Student student);
http://localhost:5000/api/values?age=11&name=jack&color=red
3.Json-简单类型,复杂类型
query没必要用json来传递简单类型
query无法将Json格式的字符串直接映射到复杂类型,可能是复杂类型会忽略其名称(student)。但是可以传递Json格式的字符串至一个字符串接收器,随后可以二次解析。
总结:query
只能传递简单类型,而接受方则可以是简单类型和复杂类型
Route
传参
- 路由也只能传递简单数据类型(路由本身不可能是复杂类型)
- 不是路由中的任何值都能做参数
[HttpGet("id")]
public ActionResult Get(int id);
http://localhost:5000/api/values/id?id=5
此时,路由中的第一个id并没有做参数,而是单纯的路由,且不可以被省略,否则会找不到路由
- 将路由当做参数
[HttpGet("{id}")]
public ActionResult Get(int id)
http://localhost:5000/api/values/6
将路由中id
加上{}
后就能将id
当做参数了。即使后面再跟别的query id
,后面的id
也不会起作用了。
如果将路由中6
改成字符串,则id
的值为默认的0
- 可以指定多级路由来传递至复杂类型
[HttpGet("{Age?}/{Name?}/{Color?}")]
public ActionResult Get(int Age, Student student)
http://localhost:5000/api/values/8/shang/red
总结:route
只能传递简单类型,而接受方则可以是简单类型和复杂类型
Header
传参
header
出传参必须加[FromHeader]
,否则无法识别
1.简单类型-简单类型
[HttpGet()]
public ActionResult Get([FromHeader]int age, [FromHeader]string name, [FromHeader]string color)
http://localhost:5000/api/values/
2.简单类型-复杂类型
[HttpGet()]
public ActionResult Get([FromHeader]Student student)
注意:无法通过简单类型传递到复杂类型
3.Header
传递的Json
字符串无法被识别
总结:header
只能传递简单类型,而接受方则也只能是简单类型
From
传参
1.简单类型-简单类型
[HttpGet()]
public ActionResult Get([FromHeader]int age, [FromHeader]string name, [FromHeader]string color)
http://localhost:5000/api/values/
2.简单类型-复杂类型
[HttpGet()]
public ActionResult Get(Student student)
http://localhost:5000/api/values/
3.无法用json传递
4.传文件
看我写的模型绑定那篇文章
总结:form
只能传递简单类型,而接受方则可以是简单类型和复杂类型
Body
传参
Body
传参也必须加上[FromBody]
属性,否则无法识别- asp.net core默认接收json格式的数据,除非设置了其他格式的解析,本文只采用json来传参。想要添加xml格式的解析,或者添加自定义解析可以看官方文档。
Body
不存在简单类型和复杂类型,就是Json
格式- 一个参数列表只能存在一个
[FromBody]
- json-简单类型
[HttpGet()]
public ActionResult Get([FromBody]string name)
body
无法传递简单数据
6.json-复杂类型
[HttpGet()]
public ActionResult Get([FromBody]Student student);
http://localhost:5000/api/values/
总结:body
只能传递json
字符串,而接受方只能是复杂类型
同时指定参数
如果这几种传参方式同时指定了值,那么会选择谁呢?
由于header
和body
都需要指定[FromXXX]
属性,所以不需要考虑了。
测试结果:
1.当form,query,route
同时指定时,选择form
http://localhost:5000/api/values/route?name=query
2.当query,route
同时指定时,选择route
http://localhost:5000/api/values/route?name=query
默认值
值类型
1.不传值
[HttpGet()]
public ActionResult Get(int a, bool b, DateTime c);
http://localhost:5000/api/values/
结果:
2.传匹配类型的值
[HttpGet()]
public ActionResult Get(int a, bool b, DateTime c);
http://localhost:5000/api/values?a=11&b=true&c=1992-01-02
结果:
3.传不匹配类型的值
[HttpGet()]
public ActionResult Get(int a, bool b, DateTime c);
http://localhost:5000/api/values?a=11&b=name&c=19920102
结果:
总结:值类型如果不传值或者传不匹配的值,则值为该类型的默认值。传匹配的值则正确接收值
引用类型
1.不传值
[HttpGet()]
public ActionResult Get(Student student,string other);
http://localhost:5000/api/values
结果:
2.传配类型的数据
[HttpGet()]
public ActionResult Get(Student student,string other);
http://localhost:5000/api/values?age=11&name=zhang&color=red&other=sui
结果:
3.引用类型不存在不匹配的数据
总结:string
类型的数据不传值则为null
,传值则为该值。复杂类型本身不为null
(实际上asp.net core会在内部调用它的默认构造函数),但是它包含的属性(值类型,引用类型)都遵循前述规则
由服务端接收到的值推断客户端的传参形式
值类型
1.服务端接收到的值为除默认值外的值
客户端传值了
2.服务端接收到了默认值
客户端没传值,客户端传了个不符合类型的值,客户端传了默认值
解决办法:
客户端没传值:用可空类型约束
客户端传了不符合类型的值:校验
ModelState
客户端传了默认值:正确,不用做
总结:要根据服务端接收到的值推断客户端的具体行为采用的方法是可空类型+ModelState
。可以判断客户端想要将值设为另外一个值还是不改动(为null
则不改动,为数值类型包括默认值则就为该值)
引用类型
1.服务端接到的值不为null
客户端传了正确的值
2.服务端接收到的值为null
客户端没传值,客户端传了空白
http://localhost:5000/api/values
http://localhost:5000/api/values?name=
http://localhost:5000/api/values?name=空格
解决办法
设置默认值
HttpContext.Form.ContainsKey("key")
总结:当一个引用类型无法判断是想修改值还是不修改值时,可以用设置默认值的方式,接收到默认值,说明是不修改值,接收null
则表示将值改为null
。还可以直接获取HttpContext
信息,判断该参数有还是没有,没有说明不需要改。有,如果为null
,则置为null
。有,如果不为null
,则置为该值。
https://blog.csdn.net/qq_34759481/article/details/102755686
详解ASP.NET Core WebApi 返回统一格式参数
业务场景:
业务需求要求,需要对 WebApi 接口服务统一返回参数,也就是把实际的结果用一定的格式包裹起来,比如下面格式:
{
"response":{
"code":200,
"msg":"Remote service error",
"result":""
}
}
具体实现:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
public class WebApiResultMiddleware : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
//根据实际需求进行具体实现
if (context.Result is ObjectResult)
{
var objectResult = context.Result as ObjectResult;
if (objectResult.Value == null)
{
context.Result = new ObjectResult(new { code = 404, sub_msg = "未找到资源", msg = "" });
}
else
{
context.Result = new ObjectResult(new { code = 200, msg = "", result = objectResult.Value });
}
}
else if (context.Result is EmptyResult)
{
context.Result = new ObjectResult(new { code = 404, sub_msg = "未找到资源", msg = "" });
}
else if (context.Result is ContentResult)
{
context.Result = new ObjectResult(new { code = 200, msg = "", result= (context.Result as ContentResult).Content });
}
else if (context.Result is StatusCodeResult)
{
context.Result = new ObjectResult(new { code = (context.Result as StatusCodeResult).StatusCode, sub_msg = "", msg = "" });
}
}
}
Startup
添加对应配置:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Filters.Add(typeof(WebApiResultMiddleware));
options.RespectBrowserAcceptHeader = true;
});
}
.net core webapi常用传递方式
一、传数组
js:
return request({
url: '',
method: 'post',
data:[1,2,3]
})
服务端写法:
[HttpPost]
public Response 方法名([FromBody] string[] ids) {}//ids的名称自定义
二、传一个对象集合(传单个对象的方法与之相同)
如实体类叫 student
:
class student{
name{get;set;}
age{get;set;}
}
js:
return request({
url: '',
dataType: "json",
contentType: "application/json;charset=utf-8",
method: 'post',
data:rows //rows是一个数组,里面是json对象,如:[{name:"a",age:1},{name:"b",age:2}]
})
服务端方法:
[HttpPost]
public Response 方法名([FromBody] List<student> rows){}//其中rows是形参名,自定义
三、同时传集合和其他参数
//js:
return request({
url: '',
dataType: "json",
contentType: "application/json;charset=utf-8",
method: 'post',
params: { a:"123" },
data:rows//rows是一个数组,里面是json对象,如:[{name:"a",age:1},{name:"b",age:2}]
})
//服务端
[HttpPost]
public Response 方法名([FromBody] List<student> rows, [FromQuery] string a)
.NET Core WebAPI post
参数传递时后端的接收方式
- 实体类
dynamic
动态类型JObject
参数- 单值参数(字符串参数)
A.前端Post
请求代码
$.ajax({
url: "/api/student/poststudent",
type: 'POST',
data:JSON.stringify({ name: "张三", age: 21 }),
success:function () {
},
dataType: "json",
contentType: "application/json"
});
B.后端接收参数方式
1. 实体类
实体类是比较简单的一种传参方式,使用频率非常高。
- 添加实体类
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
- 后台处理
Post
请求代码
[HttpPost("{id}")]
public void PostStudent(Student student)
{
}
- 接收参数结果
2.dynamic
动态类型
- 后台处理
Post
请求代码
[HttpPost("{id}")]
public void PostStudent(dynamic student)
{
var name = student.name;//name大小写与前端参数一致
var age = student.age;
}
- 接收参数结果
3.JObject
参数
- 引入
Microsoft.AspNetCore.Mvc.NewtonsoftJson
包 - 添加引用
using Newtonsoft.Json.Linq;
- 后台处理
Post
请求代码
[HttpPost("{id}")]
public void PostStudent(JObject student)
{
}
- 接收参数结果
4.单值参数(字符串参数)
只能传一个字符串参数,并且用单引号包一个双引号,双引号里为字符串内容!
2. 前端代码与以上方式不同
$.ajax({
url: "/api/student/poststudent",
type: 'POST',
data:'"name=张三,age=21"',//这里是重点!用单引号包一个双引号,双引号里为字符串内容!
success:function () {
},
dataType: "json",
contentType: "application/json"
});
- 后台处理
Post
请求代码
[HttpPost("{id}")]
public void PostStudent([FromBody] string values)
{
}
WebApi 方法参数前加[FromBody]
标识,表示该参数值应该从请求的Body
中获取,而不是从URL
中获取。不加[FromBody]
标识后台取不到参数值。
4. 接收参数结果
设置允许跨域
如果有跨域需求支持,请设置允许跨域。在Startup.cs
中添加如下代码。
- 修改
ConfigureServices
方法,添加代码如下:
//允许一个或多个来源可以跨域
services.AddCors(options =>
{
options.AddPolicy("CustomCorsPolicy", policy =>
{
// 设定允许跨域的来源,有多个可以用','隔开
policy.WithOrigins("https://localhost:5000")//只允许https://localhost:5000来源允许跨域
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
- 修改
Configure
方法,添加代码如下:
app.UseCors("CustomCorsPolicy");