第四十节:再探WebApi核心(Swagger配置+分组、跨域、路由)和基于axios测试webapi、mvc接口的异同
一. Webapi基础复习
(本节主要探讨一下webapi的核心用法、core6中写法的变化,其余基础参考之前的章节)
1. webapi的两种风格
(1).面向过程(RPC): 形如"api/控制器/方法",不关心请求方式。
(2).Rest风格(RestFul):根据http的语义来决定请求哪个接口,比如Get获取、Post新增、Put整体更新、delete删除等
2. Rest风格的优缺点
优点:(1).见名知义,不同的http谓词表示不同的操作 (2). 通过状态码反应服务器处理结果
缺点:(1).需要思考不同的操作到底用哪个谓词,不适合复杂的系统 (2).http状态码有限(3).有些客户端不支持put和delete请求
3.请求特性
[Route("api/[controller]/[action]")]
[HttpGet]、[HttpPost]、[HttpDelete]、[HttpPut]等添加到对应的操作方法上
注意:如果控制器中存在一个没有添加[HttpGet]、[HttpPost]等的public方法,Swagger就会报错,可以用[ApiExplorerSettings(IgnoreApi = true)]
4.方法的返回值
(1).Web API中Action方法的返回值如果是普通数据类型,那么返回值就会默认被序列化为Json格式。
(2).Web API中的Action方法的返回值同样支持IActionResult类型,不包含类型信息,因此Swagger等无法推断出类型,所以推荐用ActionResult<T>,它支持类型转换,从而用起来更简单。
5.方法参数接收
[FromRoute(Name="名字")],捕捉的值会被自动赋值给Action中同名的参数;如果名字不一致,可以用[FromRoute(Name="名字")]
[FromQuery]来获取QueryString中的值。如果名字一致,只要为参数添加[FromQuery]即可;而如果名字不一致,[FromQuery(Name = 名字)]
[FromForm] 从Content-Type为multipart/form-data的请求中获取数据的[FromForm]
[FromHeader]从请求报文头中获取值的[FromHeader]
二. Core6.0 webapi的变化
1. swagger的集成
(注释+jwt+分组完整代码详见框架整合:https://www.cnblogs.com/yaopengfei/p/16663423.html)
(1). 默认集成
创建项目的时候选开启openApi,则会安装 【Swashbuckle.AspNetCore】程序集, 然后在program中添加了如下代码
builder.Services.AddSwaggerGen();
app.UseSwagger();
app.UseSwaggerUI();
截至到此处,已经可以使用简单版本的OpenApi了, 访问地址:http://localhost:5033/swagger/index.html 即可,但是此时是没有注释的!!
(2).开启注释
A. csproj文件中添加:其中1591防止不加注释各种烦人提示
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
B. 然后在AddSwaggerGen中添加如下两句话,通过反射来获取注释
代码分享
using System.Reflection; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); //注册OpenApi builder.Services.AddSwaggerGen(options => { // using System.Reflection; var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); }); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { //开启OpenApi管道 app.UseSwagger(); app.UseSwaggerUI(); } //app.UseRouting(); app.UseAuthorization(); //开启跨域-需要写在静态文件的后面 app.UseCors(options => { options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); }); //开启区域路由 app.MapControllerRoute(name: "MyArea", pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"); app.MapControllers(); app.Run();
C. 再次访问 http://localhost:5033/swagger/index.html, 方法名称和参数都有了注释了
【其它用法参考:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-6.0&tabs=visual-studio】
【coreMvc中集成的步骤相同,注意:开启管道的代码要写在app.Environment.IsDevelopment()里,而不是 !app.Environment.IsDevelopment() 里】
2. 配置Swagger分组
需求:
这里以区域分组,每个区域下的Api放在一个页面里显示。
(1). Program中代码注册服务
//注册OpenApi服务
builder.Services.AddSwaggerGen(options =>
{
//1.配置分组显示Api接口
options.SwaggerDoc("Main", new OpenApiInfo { Version = "V1.0", Title = "主模块", Description = "按区域分组管理,右上角切换", });
options.SwaggerDoc("User_Areas", new OpenApiInfo { Version = "V1.0", Title = "User_Areas模块" });
options.SwaggerDoc("Permission_Areas", new OpenApiInfo { Version = "V1.0", Title = "Permission_Areas模块" });
options.DocInclusionPredicate((docName, apiDes) =>
{
if (!apiDes.TryGetMethodInfo(out MethodInfo method)) return false;
//使用ApiExplorerSettingsAttribute里面的GroupName进行特性标识
//(1).获取controller上的特性,注:method.DeclaringType只能获取controller上的特性
var controllerGroupNameList = method.DeclaringType.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName).ToList();
if (docName == "Main" && !controllerGroupNameList.Any()) return true;
//(2).获取action上的特性
var actionGroupNameList = method.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);
if (actionGroupNameList.Any())
{
return actionGroupNameList.Any(u => u == docName);
}
return controllerGroupNameList.Any(u => u == docName);
});
//2.通过反射开始注释
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
//3.配置支持JWT传递(如果有需要)
});
PS:上述的Title和Description对应的位置
(2). Program中管道配置
if (app.Environment.IsDevelopment())
{
//开启OpenApi管道
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/Main/swagger.json", "主模块");
c.SwaggerEndpoint("/swagger/User_Areas/swagger.json", "User_Areas");
c.SwaggerEndpoint("/swagger/Permission_Areas/swagger.json", "Permission_Areas");
//配置文档的展开形式:List列表(默认) None(折叠) Full(展开到参数级别)
c.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.List);
});
}
PS:上述第二个参数对应的位置
(3). 每个区域在控制器上添加特性 [ApiExplorerSettings(GroupName = "Permission_Areas")]
/// <summary>
/// User区域
/// </summary>
[Route("api/[area]/[controller]/[action]")]
[ApiController]
[Area("User_Areas")]
[ApiExplorerSettings(GroupName = "User_Areas")] //配置swagger分组
public class UserTestController : ControllerBase
{
[HttpGet]
public string GetUserInfo()
{
return "ok1234";
}
}
特别注意:ApiExplorerSettings特性也可以添加到action,即controller上不加,哪个action需要显示,则哪个上面添加。
[Route("api/[area]/[controller]/[action]")]
[ApiController]
[Area("Permission_Areas")]
public class PermissionController : ControllerBase
{
[HttpGet]
[ApiExplorerSettings(GroupName = "Permission_Areas")] //配置swagger分组
public string GetPerInfo1()
{
return "All_PerInfo1";
}
[HttpGet]
public string GetPerInfo2()
{
return "All_PerInfo2";
}
}
运行效果:
3. 跨域的解决方案
之前的方案有:JSONP、前端代理模式,现在主流采用cors的模式,这是主流的模式
原理:在服务器的响应报文头中通过access-control-allow-origin告诉浏览器允许跨域访问的域名
(详见:https://docs.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-6.0)
简洁写法:直接在管道位置添加 app.UseCors(options => { options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); }); 即可
注意:管道中要写在静态文件的后面, webapi和mvc写法相同
4. 路由规则配置
(优先级问题详见:https://www.cnblogs.com/yaopengfei/p/11849496.html ,此处重点是配置一下代码即可)
(1).区域的添加
右键→添加→新搭建基架的项目
【区域参考官网:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/controllers/areas?view=aspnetcore-6.0】
(2).区域中接口的使用- 方案1
需要标记区域名称+Route中声明路径+ApiController
[Area("User_Areas")] [ApiController] [Route("api/[area]/[controller]/[action]")]
详见:UserTestController中的GetUserInfo方法
/// <summary>
/// User区域
/// </summary>
[Route("api/[area]/[controller]/[action]")]
[ApiController]
[Area("User_Areas")]
public class UserTestController : ControllerBase
{
/// <summary>
/// 测试区域能否请求通
/// http://localhost:5033/api/User_Areas/UserTest/GetUserInfo
/// </summary>
/// <returns></returns>
[HttpGet]
public string GetUserInfo()
{
return "ok1234";
}
}
(3).区域中接口的使用- 方案2
A.全局注册在Program中,添加 app.MapControllerRoute(name: "MyArea", pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"); 开启区域路由
(视情况添加:app.UseRouting();)
B. 然后仅仅在控制器中添加区域名称即可 [Area("User_Areas")], 详见:RoleTestController中的GetRoleInfo方法
弊端:swagger中显示不出来这个接口, 因为没加[Router(xxx)]缘故
/// <summary>
/// role区域
/// </summary>
[Area("User_Areas")]
public class RoleTestController : ControllerBase
{
/// <summary>
/// 测试区域能否请求通
/// http://localhost:5033/api/User_Areas/RoleTest/GetRoleInfo
/// </summary>
/// <returns></returns>
[HttpGet]
public string GetRoleInfo()
{
return "role1234";
}
}
三. 基于axios测试webapi各种接口
废话不多说,直接上结论。
1. Get请求
(1).分参数接收, 正常接收
(2).[FromQuery]+实体接收, 正常接收
(3).从Url中获取参数,可以配合[FromRoute]改名 【不常用】
2 .Post请求-后台分参数接收
(1). 表单提交能正常请求通,但是参数为空
(2). JSON提交能正常请求通,但是参数为空
3. Post请求-JSON提交
(1). 用实体接收, 正常接收
(2). [FromBody] + 实体接收, 正常接收
(3). [FromBody] + dynamic接收, 服务端直接报错500
4. Post请求-表单提交
(1). 用实体接收, 报错:415,"Unsupported Media Type"
(2). [FromForm] + 实体接收, 正常接收
(3). [FromForm] + dynamic接收, 服务端直接报错500
5. 测试请求中Header数据的获取
(1). Get请求
A. [FromHeader]+分参数接收, 正常接收
B. [FromHeader]+实体接收, 请求成功, 但是无法拿到数据
(2). Post请求
A. [FromHeader]+分参数接收, 正常接收
B. [FromHeader]+实体接收, 请求成功,但是无法拿到数据
axios封装代码
import axios from "axios"; // 请求地址 const myUrl = " http://localhost:5033"; // 配置新建一个 axios 实例1 const myAxios1 = axios.create({ baseURL: myUrl, timeout: 20000, headers: { "X-Requested-With": "XMLHttpRequest" }, method: "post", //默认是post请求,可以自行覆盖 //默认是'application/json'提交,下面代码是手动转换成表单提交 transformRequest: [ function (data) { let ret = ""; for (let it in data) { ret += encodeURIComponent(it) + "=" + encodeURIComponent(data[it]) + "&"; } return ret.substring(0, ret.length - 1); }, ], }); // 添加请求拦截器 myAxios1.interceptors.request.use( config => { // 在发送请求之前做些什么 token config.headers.common["auth"] = `xxxx`; return config; }, error => { // 对请求错误, 针对页面async/await的写法,需要用try-catch包裹获取 return Promise.reject(error); } ); // 添加响应拦截器 myAxios1.interceptors.response.use( response => { // 响应数据的正常处理 return response.data; }, error => { // 异常数据的响应处理 const res = error.response; return Promise.reject(res); } ); // ----------------------------------------------------------axios 实例2(用于处理json提交)------------------------------------------------------- // 配置新建一个 axios 实例2 const myAxios2 = axios.create({ baseURL: myUrl, timeout: 50000, headers: { "X-Requested-With": "XMLHttpRequest" }, method: "post", //默认是post请求,可以自行覆盖 }); // 添加请求拦截器 myAxios2.interceptors.request.use( config => { // 在发送请求之前做些什么 token config.headers.common["auth"] = `xxxx`; return config; }, error => { // 对请求错误做些什么 return Promise.reject(error); } ); // 添加响应拦截器 myAxios2.interceptors.response.use( response => { // 响应数据的正常处理 return response.data; }, error => { // 异常数据的响应处理 const res = error.response; return Promise.reject(res); } ); // 导出 axios 实例 export { myAxios1, myAxios2 };
前端axios发送各种请求代码
import { myAxios1, myAxios2 } from "@/utils/request"; const myMvcBaseUrl = "http://localhost:5131"; //mvcapi的请求接口,webapi的地址写在request.js封装中 // ------------------------------------------一. 测试的webapi接口---------------------------------------------- /** * 1.测试Get请求的相关方法 */ const test1 = async () => { // 1-测试分参数接收 const result1 = await myAxios1({ url: "api/Home/GetInfor1", method: "get", params: { userName: "ypf", pwd: "123456" }, }); console.log("01-测试分参数接收:" + result1); // 2-测试用实体接收 const result2 = await myAxios1({ url: "api/Home/GetInfor2", method: "get", params: { userName: "ypf", pwd: "123456" }, }); console.log("02-测试用实体接收:" + result2); //3-测试从Url中获取参数 const result3 = await myAxios1({ url: "api/Home/GetInfor3/test1/ypf/test2/123456", method: "get", params: { userName: "ypf", pwd: "123456" }, }); console.log("03-测试从Url中获取参数:" + result3); }; /** * 2. 测试表单或json提交能否分参数接收 */ const test2 = async () => { // 1. 表单提交 const result1 = await myAxios1({ url: "api/Home/Login1", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 1. 表单提交:" + result1); // 2. Json提交 const result2 = await myAxios2({ url: "api/Home/Login1", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 2. Json提交:" + result2); }; /** * 3. 测试Json提交的三种接收情况 */ const test3 = async () => { // 1.测试Json格式提交用实体接收 const result1 = await myAxios2({ url: "api/Home/Login2", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 1.测试Json格式提交用实体接收:" + result1); // 2. 测试Json格式提交用 [FromBody] + 实体接收 const result2 = await myAxios2({ url: "api/Home/Login3", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 2.测试Json格式提交用 [FromBody] + 实体接收:" + result2); // 3. 测试Json格式提交用 [FromBody] + dynamic接收 const result3 = await myAxios2({ url: "api/Home/Login4", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 3. 测试Json格式提交用 [FromBody] + dynamic接收:" + result3); }; /** * 4. 测试表单提交的三种接收情况 */ const test4 = async () => { // 1.测试表单提交直接用实体接收 try { const result1 = await myAxios1({ url: "api/Home/Login5", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 1.测试表单提交直接用实体接收:" + result1); } catch (error) {} // 2. 测试表单提交用 [FromForm]+实体接收 const result2 = await myAxios1({ url: "api/Home/Login6", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 2.测试表单提交用 [FromForm]+实体接收:" + result2); // 3. 测试表单提交用 [FromForm]+dynamic接收 try { const result3 = await myAxios1({ url: "api/Home/Login7", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 3. 测试表单提交用 [FromForm]+dynamic接收:" + result3); } catch (error) {} }; /** * 5.下面是测试Get或Post请求获取Header中数据 */ const test5 = async () => { // 1. 测试Get请求Header的[FromHeader]+分参数接收 const result1 = await myAxios1({ url: "api/Home/GetHeaders1", method: "get", headers: { userName: "ypf", pwd: "123456" }, }); console.log("1. 测试Get请求Header的[FromHeader]+分参数接收:" + result1); // 2. 测试Get请求Header的[FromHeader]+实体接收 const result2 = await myAxios1({ url: "api/Home/GetHeaders2", method: "get", headers: { userName: "ypf", pwd: "123456" }, }); console.log("2. 测试Get请求Header的[FromHeader]+实体接收:" + result2); // 3. 测试Post请求Header的[FromHeader]+分参数接收 const result3 = await myAxios1({ url: "api/Home/GetHeaders3", method: "post", headers: { userName: "ypf", pwd: "123456" }, }); console.log("3. 测试Post请求Header的[FromHeader]+分参数接收:" + result3); // 4. 测试Post请求Header的[FromHeader]+实体接收 const result4 = await myAxios1({ url: "api/Home/GetHeaders3", method: "post", headers: { userName: "ypf", pwd: "123456" }, }); console.log("4. 测试Post请求Header的[FromHeader]+实体接收:" + result4); };
接口代码
[Route("api/[controller]/[action]")] [ApiController] public class HomeController : ControllerBase { /******************************************一. 下面是测试Get请求的相关方法***************************************************/ /// <summary> /// 01-测试分参数接收 /// </summary> /// 结论:正常接收 /// <param name="userName">用户名</param> /// <param name="pwd">密码</param> /// <returns>用户名+密码组成的字符串</returns> [HttpGet] public string GetInfor1(string userName, string pwd) { return $"{userName}+{pwd}"; } /// <summary> /// 02-测试用实体接收 /// </summary> /// 结论:正常接收 /// <param name="model"></param> /// <returns></returns> [HttpGet] public string GetInfor2([FromQuery] UserInfo model) { return $"{model.userName}+{model.pwd}"; } /// <summary> /// 03-测试从Url中获取参数 /// GetInfor3-测试从url /xx/xx/xx 获取内容 /// </summary> /// http://localhost:5033/api/Home/GetInfor3/test1/ypf/test2/123456 /// 结论:正常接收 /// <param name="myName"></param> /// <param name="myPwd2"></param> /// <returns></returns> [HttpGet("test1/{myName}/test2/{myPwd}")] public string GetInfor3(string myName, [FromRoute(Name = "myPwd")] string myPwd2) { return $"{myName}+{myPwd2}"; } /**************************************二. 下面是测试POST请求的相关方法***************************************************/ /**************************************2.1. 测试表单或json提交能否分参数接收**************************************************/ /// <summary> /// 01-测试表单提交 和 Json提交分参数接收的情况 /// </summary> /// http://localhost:5033/api/Home/Login1 /// 结论: /// A. 表单提交能正常请求通,但是参数为空 /// B. JSON提交能正常请求通,但是参数为空 /// <param name="userName"></param> /// <param name="pwd"></param> /// <returns></returns> [HttpPost] public string Login1(string userName, string pwd) { return $"{userName}+{pwd}"; } /**************************************2.2. 测试Json提交的三种接收情况**************************************************/ /// <summary> /// 01-测试Json格式提交用实体接收 /// </summary> /// postMan中的参数:{ "userName": "ypf", "pwd": "123456"} /// 结论:正常接收 /// <param name="model"></param> /// <returns></returns> [HttpPost] public string Login2(UserInfo model) { return $"{model.userName}+{model.pwd}"; } /// <summary> /// 02-测试Json格式提交用 [FromBody] + 实体接收 /// </summary> /// postMan中的参数:{ "userName": "ypf", "pwd": "123456"} /// 结论:正常接收 /// <param name="model"></param> /// <returns></returns> [HttpPost] public string Login3([FromBody] UserInfo model) { return $"{model.userName}+{model.pwd}"; } /// <summary> /// 03-测试Json格式提交用 [FromBody] + dynamic接收 /// </summary> /// postMan中的参数:{ "userName": "ypf", "pwd": "123456"} /// 结论:服务端直接报错500 /// <param name="model"></param> /// <returns></returns> [HttpPost] public string Login4([FromBody] dynamic model) { return $"{model.userName}+{model.pwd}"; } /**************************************2.3. 测试表单提交的三种接收情况**************************************************/ /// <summary> /// 01-测试表单提交直接用实体接收 /// </summary> /// 结论:报错:415,"Unsupported Media Type" /// <param name="model"></param> /// <returns></returns> [HttpPost] public string Login5(UserInfo model) { return $"{model.userName}+{model.pwd}"; } /// <summary> /// 02-测试表单提交用 [FromForm]+实体接收 /// </summary> /// 结论:正常接收 /// <param name="model"></param> /// <returns></returns> [HttpPost] public string Login6([FromForm] UserInfo model) { return $"{model.userName}+{model.pwd}"; } /// <summary> /// 03-测试表单提交用 [FromForm]+dynamic接收 /// </summary> /// 结论:服务端报错500 /// <param name="model"></param> /// <returns></returns> [HttpPost] public string Login7([FromForm] dynamic model) { return $"{model.userName}+{model.pwd}"; } /******************************************三. 下面是测试Get或Post请求获取Header中数据***************************************************/ /// <summary> /// 01-测试Get请求Header的[FromHeader]+分参数接收 /// </summary> /// 结论:正常接收 /// <param name="userName"></param> /// <param name="pwd"></param> /// <returns></returns> [HttpGet] public string GetHeaders1([FromHeader] string userName, [FromHeader] string pwd) { return $"{userName}+{pwd}"; } /// <summary> /// 02-测试Get请求Header的[FromHeader]+实体接收 /// </summary> /// 结论:请求成功,但是无法拿到数据 /// <param name="model"></param> /// <returns></returns> [HttpGet] public string GetHeaders2([FromHeader] UserInfo model) { return $"{model.userName}+{model.pwd}"; } /// <summary> /// 03-测试Post请求Header的[FromHeader]+分参数接收 /// </summary> /// 结论:正常接收 /// <param name="userName"></param> /// <param name="pwd"></param> /// <returns></returns> [HttpPost] public string GetHeaders3([FromHeader] string userName, [FromHeader] string pwd) { return $"{userName}+{pwd}"; } /// <summary> /// 04-测试Post请求Header的[FromHeader]+实体接收 /// </summary> /// 结论:请求成功,但是无法拿到数据 /// <param name="model"></param> /// <returns></returns> [HttpPost] public string GetHeaders4([FromHeader] UserInfo model) { return $"{model.userName}+{model.pwd}"; } }
四. 测试mvc中各种接口
(主要区别:mvc控制器继承Controller, webapi控制器继承ControllerBase; 另外mvc控制器上不加特性 [ApiController])
直接上结论
1. Get请求
(1). 分参数接收, 正常接收
(2). [FromQuery]+实体接收, 正常接收
(3). 从Url中获取参数,可以配合[FromRoute]改名 【不常用】
2 .Post请求-后台分参数接收
(1). 表单提交, 正常接收 【和webapi不同】
(2). JSON提交能正常请求通, 但是参数为空
3. Post请求-JSON提交
(1). 用实体接收, 能正常请求通,但是参数为空 【和webapi不同】
(2). [FromBody] + 实体接收, 正常接收
(3). [FromBody] + dynamic接收, 服务端直接报错500
4. Post请求-表单提交
(1). 用实体接收, 正常接收 【和webapi不同】
(2). [FromForm] + 实体接收, 正常接收
(3). [FromForm] + dynamic接收, 服务端直接报错500
5. 测试请求中Header数据的获取
(1). Get请求
A. [FromHeader]+分参数接收, 正常接收
B. [FromHeader]+实体接收, 请求成功,但是无法拿到数据
(2). Post请求
A. [FromHeader]+分参数接收, 正常接收
B. [FromHeader]+实体接收, 请求成功,但是无法拿到数据
总结:
A. mvc中post请求的表单提交, 后台可以分参数接收,这个就很方便了, 但是webapi不可以
B. mvc中post请求的json提交, mvc中实体前必须加[FromBody]才能用, 但是webapi中可以不加
C. mvc中post请求的表单提交, 后台可以用实体直接接收, 但是webapi不可以,webapi必须加[FromForm]才能用
前端调用代码
// ------------------------------------------二. 测试的coreMvc接口---------------------------------------------- /** * 1.测试Get请求的相关方法 */ const test1mvc = async () => { // 1-测试分参数接收 const result1 = await myAxios1({ baseURL: myMvcBaseUrl, url: "api/Home/GetInfor1", method: "get", params: { userName: "ypf", pwd: "123456" }, }); console.log("01-测试分参数接收:" + result1); // 2-测试用实体接收 const result2 = await myAxios1({ baseURL: myMvcBaseUrl, url: "api/Home/GetInfor2", method: "get", params: { userName: "ypf", pwd: "123456" }, }); console.log("02-测试用实体接收:" + result2); //3-测试从Url中获取参数 const result3 = await myAxios1({ baseURL: myMvcBaseUrl, url: "api/Home/GetInfor3/test1/ypf/test2/123456", method: "get", params: { userName: "ypf", pwd: "123456" }, }); console.log("03-测试从Url中获取参数:" + result3); }; /** * 2. 测试表单或json提交能否分参数接收 */ const test2mvc = async () => { // 1. 表单提交 const result1 = await myAxios1({ baseURL: myMvcBaseUrl, url: "api/Home/Login1", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 1. 表单提交:" + result1); // 2. Json提交 const result2 = await myAxios2({ baseURL: myMvcBaseUrl, url: "api/Home/Login1", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 2. Json提交:" + result2); }; /** * 3. 测试Json提交的三种接收情况 */ const test3mvc = async () => { // 1.测试Json格式提交用实体接收 const result1 = await myAxios2({ baseURL: myMvcBaseUrl, url: "api/Home/Login2", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 1.测试Json格式提交用实体接收:" + result1); // 2. 测试Json格式提交用 [FromBody] + 实体接收 const result2 = await myAxios2({ baseURL: myMvcBaseUrl, url: "api/Home/Login3", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 2.测试Json格式提交用 [FromBody] + 实体接收:" + result2); // 3. 测试Json格式提交用 [FromBody] + dynamic接收 const result3 = await myAxios2({ baseURL: myMvcBaseUrl, url: "api/Home/Login4", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 3. 测试Json格式提交用 [FromBody] + dynamic接收:" + result3); }; /** * 4. 测试表单提交的三种接收情况 */ const test4mvc = async () => { // 1.测试表单提交直接用实体接收 try { const result1 = await myAxios1({ baseURL: myMvcBaseUrl, url: "api/Home/Login5", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 1.测试表单提交直接用实体接收:" + result1); } catch (error) {} // 2. 测试表单提交用 [FromForm]+实体接收 const result2 = await myAxios1({ baseURL: myMvcBaseUrl, url: "api/Home/Login6", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 2.测试表单提交用 [FromForm]+实体接收:" + result2); // 3. 测试表单提交用 [FromForm]+dynamic接收 try { const result3 = await myAxios1({ baseURL: myMvcBaseUrl, url: "api/Home/Login7", method: "post", data: { userName: "ypf", pwd: "123456" }, }); console.log(" 3. 测试表单提交用 [FromForm]+dynamic接收:" + result3); } catch (error) {} }; /** * 5.下面是测试Get或Post请求获取Header中数据 */ const test5mvc = async () => { // 1. 测试Get请求Header的[FromHeader]+分参数接收 const result1 = await myAxios1({ baseURL: myMvcBaseUrl, url: "api/Home/GetHeaders1", method: "get", headers: { userName: "ypf", pwd: "123456" }, }); console.log("1. 测试Get请求Header的[FromHeader]+分参数接收:" + result1); // 2. 测试Get请求Header的[FromHeader]+实体接收 const result2 = await myAxios1({ baseURL: myMvcBaseUrl, url: "api/Home/GetHeaders2", method: "get", headers: { userName: "ypf", pwd: "123456" }, }); console.log("2. 测试Get请求Header的[FromHeader]+实体接收:" + result2); // 3. 测试Post请求Header的[FromHeader]+分参数接收 const result3 = await myAxios1({ baseURL: myMvcBaseUrl, url: "api/Home/GetHeaders3", method: "post", headers: { userName: "ypf", pwd: "123456" }, }); console.log("3. 测试Post请求Header的[FromHeader]+分参数接收:" + result3); // 4. 测试Post请求Header的[FromHeader]+实体接收 const result4 = await myAxios1({ baseURL: myMvcBaseUrl, url: "api/Home/GetHeaders3", method: "post", headers: { userName: "ypf", pwd: "123456" }, }); console.log("4. 测试Post请求Header的[FromHeader]+实体接收:" + result4); };
后端接口代码
[Route("api/[controller]/[action]")] public class HomeController : Controller { /******************************************一. 下面是测试Get请求的相关方法***************************************************/ /// <summary> /// 01-测试分参数接收 /// </summary> /// http://localhost:5131/api/Home/GetInfor1?userName=ypf&pwd=123456 /// 结论:正常接收 /// <param name="userName"></param> /// <param name="pwd"></param> /// <returns></returns> [HttpGet] public string GetInfor1(string userName, string pwd) { return $"{userName}+{pwd}"; } /// <summary> /// 02-测试用实体接收 /// </summary> /// http://localhost:5131/api/Home/GetInfor2?userName=ypf&pwd=123456 /// 结论:正常接收 /// <param name="model"></param> /// <returns></returns> [HttpGet] public string GetInfor2([FromQuery] UserInfo model) { return $"{model.userName}+{model.pwd}"; } /// <summary> /// 03-测试从Url中获取参数 /// GetInfor3-测试从url /xx/xx/xx 获取内容 /// </summary> /// http://localhost:5131/api/Home/GetInfor3/test1/ypf/test2/123456 /// 结论:正常接收 /// <param name="myName"></param> /// <param name="myPwd"></param> /// <returns></returns> [HttpGet("test1/{myName}/test2/{myPwd}")] public string GetInfor3(string myName, [FromRoute(Name = "myPwd")] string myPwd2) { return $"{myName}+{myPwd2}"; } /**************************************二. 下面是测试POST请求的相关方法***************************************************/ /**************************************2.1. 测试表单或json提交能否分参数接收**************************************************/ /// <summary> /// 01-测试表单提交 和 Json提交分参数接收的情况 【和webapi有区别!!】 /// </summary> /// http://localhost:5131/api/Home/Login1 /// 结论: /// A. 表单提交正常接收 /// B. JSON提交能正常请求通,但是参数为空 /// <param name="userName"></param> /// <param name="pwd"></param> /// <returns></returns> [HttpPost] public string Login1(string userName, string pwd) { return $"{userName}+{pwd}"; } /**************************************2.2. 测试Json提交的三种接收情况**************************************************/ /// <summary> /// 01-测试Json格式提交用实体接收【和webapi有区别!!】 /// </summary> /// postMan中的参数:{ "userName": "ypf", "pwd": "123456"} /// 结论:能正常请求通,但是参数为空 /// <param name="model"></param> /// <returns></returns> [HttpPost] public string Login2(UserInfo model) { return $"{model.userName}+{model.pwd}"; } /// <summary> /// 02-测试Json格式提交用 [FromBody] + 实体接收 /// </summary> /// postMan中的参数:{ "userName": "ypf", "pwd": "123456"} /// 结论:正常接收 /// <param name="model"></param> /// <returns></returns> [HttpPost] public string Login3([FromBody] UserInfo model) { return $"{model.userName}+{model.pwd}"; } /// <summary> /// 03-测试Json格式提交用 [FromBody] + dynamic接收 /// </summary> /// postMan中的参数:{ "userName": "ypf", "pwd": "123456"} /// 结论:服务端直接报错 /// <param name="model"></param> /// <returns></returns> [HttpPost] public string Login4([FromBody] dynamic model) { return $"{model.userName}+{model.pwd}"; } /**************************************2.3. 测试表单提交的两种种接收情况**************************************************/ /// <summary> /// 01-测试表单提交直接用实体接收【和webapi有区别!!】 /// </summary> /// 结论:正常接收 /// <param name="model"></param> /// <returns></returns> [HttpPost] public string Login5(UserInfo model) { return $"{model.userName}+{model.pwd}"; } /// <summary> /// 02-测试表单提交用 [FromForm]+实体接收 /// </summary> /// 结论:正常接收 /// <param name="model"></param> /// <returns></returns> [HttpPost] public string Login6([FromForm] UserInfo model) { return $"{model.userName}+{model.pwd}"; } /// <summary> /// 03-测试表单提交用 [FromForm]+dynamic接收 /// </summary> /// 结论:服务端报错 /// <param name="model"></param> /// <returns></returns> [HttpPost] public string Login7([FromForm] dynamic model) { return $"{model.userName}+{model.pwd}"; } /******************************************三. 下面是测试Get或Post请求获取Header中数据***************************************************/ /// <summary> /// 01-测试Get请求Header的[FromHeader]+分参数接收 /// </summary> /// 结论:正常接收 /// <param name="userName"></param> /// <param name="pwd"></param> /// <returns></returns> [HttpGet] public string GetHeaders1([FromHeader] string userName, [FromHeader] string pwd) { return $"{userName}+{pwd}"; } /// <summary> /// 02-测试Get请求Header的[FromHeader]+实体接收 /// </summary> /// 结论:请求成功,但是无法拿到数据 /// <param name="userName"></param> /// <param name="pwd"></param> /// <returns></returns> [HttpGet] public string GetHeaders2([FromHeader] UserInfo model) { return $"{model.userName}+{model.pwd}"; } /// <summary> /// 03-测试Post请求Header的[FromHeader]+分参数接收 /// </summary> /// 结论:正常接收 /// <param name="userName"></param> /// <param name="pwd"></param> /// <returns></returns> [HttpPost] public string GetHeaders3([FromHeader] string userName, [FromHeader] string pwd) { return $"{userName}+{pwd}"; } /// <summary> /// 04-测试Post请求Header的[FromHeader]+实体接收 /// </summary> /// 结论:请求成功,但是无法拿到数据 /// <param name="userName"></param> /// <param name="pwd"></param> /// <returns></returns> [HttpPost] public string GetHeaders4([FromHeader] UserInfo model) { return $"{model.userName}+{model.pwd}"; } }
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。