第四十节:再探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();
View Code

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 };
View Code

前端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);
};
View Code

接口代码 

 [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}";
        }


    }
View Code

 

 

四. 测试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);
};
View Code

后端接口代码 

[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}";
        }
    }
View Code

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2022-01-09 19:38  Yaopengfei  阅读(638)  评论(2编辑  收藏  举报