目的

通过一个简单的项目,在原来的文章基础上完善一下常用的几种WebApi编写方式以及请求方式,一方面是用于给我一个前端朋友用来学习调用接口,另一方面让我测试HttpClient的一些效果。

本文示例代码环境:vs2022、net6

准备

新创建了一个.Net WebAPI程序,安装组件

<ItemGroup>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.3.1" />
</ItemGroup>

ConfigureServices配置NewtonsoftJson以及Automapper和操作数据库代码(为了省事,删除了一些不影响当前效果的代码)

public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddNewtonsoftJson(); services.AddEndpointsApiExplorer();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "MyWebApi", Version = "v1" });
}); //注入AutoMapper
services.AddAutoMapper(Assembly.GetExecutingAssembly().DefinedTypes.Where(t => typeof(Profile).GetTypeInfo()
.IsAssignableFrom(t.AsType())).Select(t => t.AsType()).ToArray());
}

注意:在Net core3.0以后,微软移除了Newtonsoft.Json,而使用了System.Text.Json,所以依赖于Newtonsoft.Json的组件将不可用,需要安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson 包

因为仅仅作为演示,所以我只是新增一个控制器,里面包含了get、post、put、patch、delete几种类型的接口。这里先不贴代码,一点一点看。通过一个用户的添加、修改、删除作为一个演示的流程。

记得配置允许跨域请求,要不js请求会因为跨域问题而报错。详情看此处

数据来源就是控制器里面的一个静态变量,格式如下

public class UserDto
{
public long UserId { get; set; } public string Name { get; set; } public string Sex { get; set; }
}

静态变量如下

private static readonly List<UserDto> _userDtoList = Enumerable.Range(0, 100)
.Select(t => new UserDto
{
Name = "张三" + t,
Sex = "男",
UserId = 6974150586715897857 + t
}).ToList();

后端请求的方法我使用的是HttpClient,并且做成了一个公共类,部分需要用到的如下

public class HttpClientHelper: IHttpHelper
{
private readonly System.Net.Http.HttpClient _client; /// <summary>
/// 构造函数
/// </summary>
/// <param name="httpClientFactory"></param>
public HttpClientHelper(IHttpClientFactory httpClientFactory)
{
_client = httpClientFactory.CreateClient();
} private void VerifyParam(string url, string jwtToken, IDictionary<string, string> headers)
{
_client.DefaultRequestHeaders.Clear();
if (string.IsNullOrWhiteSpace(url))
{
throw new ArgumentNullException("url不能为null");
}
if (!string.IsNullOrWhiteSpace(jwtToken))
{
_client.DefaultRequestHeaders.Add("Authorization", $"Bearer {jwtToken}");
}
if (headers?.Count > 0)
{
foreach (var (key, value) in headers)
{
_client.DefaultRequestHeaders.Add(key, value);
}
}
} private static async Task<T> ConvertResponseResult<T>(HttpResponseMessage httpResponse)
{
//确保成功完成,不是成功就返回具体错误信息
httpResponse.EnsureSuccessStatusCode();
var resStr = await httpResponse.Content.ReadAsStringAsync();
if (typeof(T) == typeof(string))
return (T)Convert.ChangeType(resStr, typeof(string)); return JsonConvert.DeserializeObject<T>(resStr);
}
}

操作

请求头传递token只是为了演示请求头传递参数的写法,token为伪值

GET

从web服务检索数据。传递参数的本质是url字符串拼接,Request-Head头部传递,Request-Body中不能传递(严格点说不建议,因为我使用Apifox等工具可以在body中传值,swagger会提示 Request with GET/HEAD method cannot have body)

Query格式

编写用户id查询用户信息接口

[HttpGet("user/details")]
public UserDto GetUserDetails(long userId)
{
if (!_userDtoList.Any(t => t.UserId == userId))
throw new ParameterException("未找到用户标识");
return _userDtoList.Find(t => t.UserId == userId);
}

前端请求

$(function () {
$.ajax({
type: "get",
url: "http://localhost:5000/api/HttpSample/user/details?userId=6974150586715897857",
headers: { "Authorization": "Bearer 123456" },
contentType: "application/json",
success: function (data, status) {
if (status == "success") {
console.log(JSON.stringify(data));
}
}
}); var postdata = { userId: "6974150586715897857" };
$.ajax({
type: "get",
headers:{"Authorization":"Bearer 123456"},
url: "http://localhost:5000/api/HttpSample/user/details",
data: postdata,
success: function (data, status) {
if (status == "success") {
console.log(JSON.stringify(data));
}
}
});
});

后端请求

var token = "123456";//此处token是伪值
var result = await _httpHelper.GetAsync<ResultModel<UserDto>>("http://localhost:5000/api/HttpSample/user/details?userId=6974150586715897857", token);

这里的_httpHelper是注入的IHttpHelper(下面其他的方法一样),对应的GetAsync为

public async Task<T> GetAsync<T>(string url, string jwtToken = "", IDictionary<string, string> headers = null)
{
VerifyParam(url, jwtToken, headers); var response = await _client.GetAsync(url).ConfigureAwait(false);
return await ConvertResponseResult<T>(response).ConfigureAwait(false);
}

接口工具请求

url:http://localhost:5000/api/HttpSample/user/details?userId=6974150586715897857

并且再请求头增加:Authorization,值为Bearer xxxx

返回结果如下

POST

在web服务上创建新的数据项。约定用于向服务端提交数据操作,请求时候参数放在参数FromBody传递

Json格式

演示添加用户操作

请求类

public class UserDto
{
public long UserId { get; set; } public string Name { get; set; } public string Sex { get; set; }
}

接口代码示例

[HttpPost("user/add")]
public bool Add([FromBody] UserDto request)
{
if (_userDtoList.Any(t => t.UserId == request.UserId))
throw new ParameterException("用户标识已经存在");
Console.WriteLine(DateTime.Now + " " + HttpContext.Request.Headers["Authorization"].FirstOrDefault());
_userDtoList.Add(request);
return true;
}

前端请求

$(function () {
var param = { userId: "8974150586715897867", name: "老八", sex: "女" };
$.ajax({
type: "post",
dataType: 'json',
contentType: "application/json",
headers: { "Authorization": "Bearer 123456" },
url: "http://localhost:5000/api/HttpSample/user/add",
data: JSON.stringify(param),
success: function (data) {
if (status == "success") {
console.log(JSON.stringify(data));
}
}
});
});

后端请求

var token = "123456";//此处token是伪值
var url = "http://localhost:5000/api/HttpSample/user/add"; var usedto = new UserDto
{
UserId = 123456,
Name = "李四",
Sex = "女"
}; var result = await _httpHelper.PostAsync<ResultModel<bool>>(url, usedto, token); public async Task<T> PostAsync<T>(string url, object data, string jwtToken = "", IDictionary<string, string> headers = null)
{
VerifyParam(url, jwtToken, headers);
var jsonData = data is string ? data.ToString() : JsonConvert.SerializeObject(data);
using var content = new StringContent(jsonData ?? string.Empty, Encoding.UTF8, "application/json");
var response = await _client.PostAsync(url, content).ConfigureAwait(false);
return await ConvertResponseResult<T>(response).ConfigureAwait(false);
}

接口工具请求

传递参数格式为json格式,请求头部默认添加:"Content-Type", "application/json"

x-www-form-unlencoded格式

更新用户姓名

[HttpPost("user/updatename")]
public bool UpdateName([FromForm] long userId, [FromForm] string name)
{
var entity = _userDtoList.Find(t => t.UserId == userId);
if (entity is null)
throw new ParameterException("用户标识不存在"); entity.Name = name; return true;
}

前端请求

$(function () {
var postdata = { userId: "6974150586715897857", name: "赵六" };
$.ajax({
type: "post",
headers: { "Authorization": "Bearer 123456" },
url: "http://localhost:5000/api/HttpSample/user/updatename",
data: postdata,
success: function (data, status) {
if (status == "success") {
console.log(JSON.stringify(data));
}
}
});
});

后端请求

var token = "123456";//此处token是伪值
var url = "http://localhost:5000/api/HttpSample/user/updatename";
var dic = new Dictionary<string, string>
{
{ "userId","6974150586715897857"},
{ "name","王五"}
};
var result = await _httpHelper.PostFormDataAsync<ResultModel<bool>>(url, dic, token); public async Task<T> PostFormDataAsync<T>(string url, Dictionary<string, string> data, string jwtToken = "", IDictionary<string, string> headers = null)
{
VerifyParam(url, jwtToken, headers);
var httpContent = new FormUrlEncodedContent(data);
var response = await _client.PostAsync(url, httpContent).ConfigureAwait(false);
return await ConvertResponseResult<T>(response).ConfigureAwait(false);
}

接口工具请求

选择post请求,参数在Body,然后选择x-www-form-unlencoded格式。

Form-data格式

模拟上传用户头像操作

[HttpPost("user/uploadImg")]
public string Upload([FromForm] IFormFile img, [FromForm] long userId)
{
if (img is null)
throw new ParameterException("用户头像不能为null"); Console.WriteLine(HttpContext.Request.Headers["Authorization"].FirstOrDefault());
var entity = _userDtoList.Find(t => t.UserId == userId);
if (entity is null)
throw new ParameterException("用户标识不存在"); return img.FileName;
}

注意:当你上传大于30000000字节长度的文件时候,需要修改上传文件的默认限制

前端请求

$(function () {
$("#tijiao").click(function () {
//logoimg是<input type="file" id="logoimg"" />
var files = $("#logoimg").prop('files'); //获取到文件列表 var formData = new FormData();
formData.append("userId", "6974150586715897857");
formData.append("img", files[0], "1122.jpg");//图片文件流 console.log(formData);
$.ajax({
type: 'post',
url: "http://localhost:5000/api/HttpSample/user/uploadImg",
headers: {
"Authorization": "Bearer 123456"
},
mimeType: "multipart/form-data",
processData: false,
contentType: false,
data: formData,
success: function (data) {
//后端Httpclient请求成功后返回过来的结果
console.log(data);
}
});
});
});

后端请求

var url = "http://localhost:5000/api/HttpSample/user/uploadImg";

var formData = new MultipartFormDataContent();

var bytes = System.IO.File.ReadAllBytes("D:\\Downloads\\11111.jpg");
var byteContent = new ByteArrayContent(bytes);
byteContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data")
{
Name = "img",
FileName = "111.jpg"
};
formData.Add(byteContent); // 写法一
formData.Add(new StringContent("6974150586715897857"), "userId"); // 写法二
var byteContent2 = new ByteArrayContent(Encoding.UTF8.GetBytes("天气"));
byteContent2.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data")
{
Name = "name",
};
formData.Add(byteContent2); var headerDic = new Dictionary<string, string>
{
{ "Authorization","Bearer 123456"},
}; var result = await _httpHelper.PostFormDataAsync<ResultModel<string>>(url, formData, headerDic); public async Task<T> PostFormDataAsync<T>(string url, MultipartFormDataContent data, IDictionary<string, string> headers = null)
{
VerifyParam(url, "", headers);
var result = await _client.PostAsync(url, data).ConfigureAwait(false);
return await ConvertResponseResult<T>(result);
}

接口工具请求

选择Body=>form-data

PUT

更新web服务上的数据项。

Json格式

更新用户信息

[HttpPut("user/update")]
public bool Update(UserDto userDto)
{
if (userDto is null)
throw new ParameterException("参数不能为空"); Console.WriteLine(DateTime.Now + " " + HttpContext.Request.Headers["Authorization"].FirstOrDefault());
var currUser = _userDtoList.Find(t => t.UserId == userDto.UserId);
if (currUser is null)
throw new ParameterException("用户标识不存在"); currUser.Name = userDto.Name;
currUser.Sex = userDto.Sex;
return true;
}

前端请求

$(function () {
var param = { userId: "6974150586715897859", name: "老八", sex: "女" };
$.ajax({
type: "put",
dataType: 'json',
contentType: "application/json",
headers: { "Authorization": "Bearer 123456" },
url: "http://localhost:5000/api/HttpSample/user/update",
data: JSON.stringify(param),
success: function (data, status) {
if (status == "success") {
console.log(JSON.stringify(data));
}
}
});
});

后端请求

var token = "123456";//此处token是伪值

var usedto = new UserDto
{
UserId = 6974150586715897859,
Name = "老八",
Sex = "女"
}; var url = "http://localhost:5000/api/HttpSample/user/update"; var result = await _httpHelper.PutAsync<ResultModel<bool>>(url, usedto, token);
return JsonConvert.SerializeObject(result); public async Task<T> PutAsync<T>(string url, object data, string jwtToken = "", IDictionary<string, string> headers = null)
{
VerifyParam(url, jwtToken, headers);
var jsonData = data is string ? data.ToString() : JsonConvert.SerializeObject(data);
using var content = new StringContent(jsonData ?? string.Empty, Encoding.UTF8, "application/json");
var response = await _client.PutAsync(url, content).ConfigureAwait(false);
return await ConvertResponseResult<T>(response).ConfigureAwait(false);
}

接口工具请求

URL:http://localhost:5000/api/HttpSample/user/update

参数传递:Body=>json

DELETE

删除web服务上的数据项。

Query格式

删除用户信息

[HttpDelete("user")]
public bool Delete(long userId)
{
var entity = _userDtoList.Find(t => t.UserId == userId);
if (entity is null)
throw new ParameterException("用户标识不存在"); Console.WriteLine(DateTime.Now + " " + HttpContext.Request.Headers["Authorization"].FirstOrDefault());
_userDtoList.Remove(entity);
return true;
}

前端请求

$(function () {
$.ajax({
type: "DELETE",
url: "http://localhost:5000/api/HttpSample/user?userId=6974150586715897861",
headers: { "Authorization": "Bearer 123456" },
success: function (data, status) {
if (status == "success") {
console.log(JSON.stringify(data));
}
}
});
});

后端请求

var token = "123456";//此处token是伪值
var url = "http://localhost:5000/api/HttpSample/user?userId=6974150586715897862"; var result = await _httpHelper.DeleteAsync<ResultModel<bool>>(url, token); public async Task<T> DeleteAsync<T>(string url, string jwtToken = "", IDictionary<string, string> headers = null)
{
VerifyParam(url, jwtToken, headers);
var response = await _client.DeleteAsync(url).ConfigureAwait(false);
return await ConvertResponseResult<T>(response).ConfigureAwait(false);
}

接口工具请求

URL:http://localhost:5000/api/HttpSample/user?userId=6974150586715897859

Patch

通过描述有关如何修改项的一组说明,更新web服务上的数据项。

请求格式如下:

[{"op" : "replace", "path" : "/PassWord", "value" : "222222"}]

op属性指示操作的类型,path属性指示要更新的元素,value属性提供新值。

add:添加属性或数组元素。 对于现有属性:设置值。

remove:删除属性或数组元素。

replace:替换操作

为了支持该请求方式,需要安装nuget包Microsoft.AspNetCore.Mvc.NewtonsoftJson。

参考文档:https://docs.microsoft.com/zh-cn/aspnet/core/web-api/jsonpatch?view=aspnetcore-6.0

Json格式

在此用于更新数据

[HttpPatch("user/update2/{userId}")]
public UserDto Update2([FromRoute] long userId, JsonPatchDocument<UserDto> jsonPatch, [FromServices] IMapper mapper)
{
var entity = _userDtoList.Find(t => t.UserId == userId);
if (entity is null)
throw new ParameterException("用户标识无效"); var dto = mapper.Map<UserDto>(entity);
jsonPatch.ApplyTo(dto, ModelState); var user = _userDtoList.Find(t => t.UserId == userId);
mapper.Map(dto, user);
return user;
}

前端请求

演示根据用户id去更新用户的姓名

$(function () {
var par = [{ "op": "replace", "path": "/name", "value": "老六" }];
$.ajax({
type: "Patch",
url: "http://localhost:5000/api/HttpSample/user/update2/6974150586715897857",
headers: { "Authorization": "Bearer 123456" },
contentType: "application/json",
data: JSON.stringify(par),
success: function (result) {
console.log(result);
}
});
});

后端请求

var token = "123456";//此处token是伪值
var url = "http://localhost:5000/api/HttpSample/user/update2/6974150586715897859";
var content = "[{\"op\":\"replace\",\"path\":\"/name\",\"value\":\"小七七\"}]";
var result = await _httpHelper.PatchAsync<ResultModel<UserDto>>(url, content, token); public async Task<T> PatchAsync<T>(string url, object data, string jwtToken = "", IDictionary<string, string> headers = null)
{
VerifyParam(url, jwtToken, headers);
var jsonData = data is string ? data.ToString() : JsonConvert.SerializeObject(data);
using var content = new StringContent(jsonData ?? string.Empty, Encoding.UTF8, "application/json");
var response = await _client.PatchAsync(url, content).ConfigureAwait(false);
return await ConvertResponseResult<T>(response).ConfigureAwait(false);
}

接口工具请求

参数传递:Body=>json

.Net之接口小知识的更多相关文章

  1. 【C#小知识】C#中一些易混淆概念总结(四)---------解析Console.WriteLine() 分类: C# 2014-02-05 17:18 1060人阅读 评论(0) 收藏

    目录: [C#小知识]C#中一些易混淆概念总结 [C#小知识]C#中一些易混淆概念总结(二) [C#小知识]C#中一些易混淆概念总结(三) ------------------------------ ...

  2. Java基础小知识(一)

     序言:“不积跬步,无以至千里.不积小流,无以成江海.”每一个庞大的知识架构都是由无数个小知识点慢慢积累起来的,没有量变的积累,就没有质变上的飞跃,成功往往离不开积累. 今天就和大家分享一些我在学习J ...

  3. Autofac 依赖注入小知识

    Autofac 依赖注入小知识 控制反转/依赖注入 IOC/DI 依赖接口而不依赖于实现,是面向对象的六大设计原则(SOLID)之一.即依赖倒置原则(Dependence Inversion Prin ...

  4. 蓝牙Bluetooth技术小知识

    蓝牙Bluetooth技术以及广泛的应用于各种设备,并将继续在物联网IoT领域担任重要角色.下面搜集整理了一些关于蓝牙技术的小知识,以备参考. 蓝牙Bluetooth技术始创于1994年,其名字来源于 ...

  5. HTML+CSS中的一些小知识

    今天分享一些HTML.CSS的小知识,希望能够对大家有所帮助! 1.解决网页乱码的问题:最重要的是要保证各个环节的字符编码一致! (1)编辑器的编辑环境的字符集(默认字符集):Crtl+U 常见的编码 ...

  6. iOS APP开发的小知识(分享)

          亿合科技小编发现从2007年第一款智能手机横空出世,由此开启了人们的移动智能时代.我们从一开始对APP的陌生,到现在的爱不释手,可见APP开发的出现对我们的生活改变有多巨大.而iOS AP ...

  7. Unix系统小知识(转)

    Unix操作系统的小知识 2.VI添加行号/翻页/清屏 .在对话模式时(即输完Esc再输入: ),输入“:set number”可以将编辑的文本加上行号.跟玩俄罗斯方块一样方便的上下左右移动箭头的快捷 ...

  8. salesforce 零基础开发入门学习(十)IDE便捷小知识

    在这里介绍两个IDE的便捷开发的小知识. 一) 本地调试 由于salesforce代码只能提交以后才能调试,所以很多时候调试代码很麻烦.新版增加了一个特性:即可以在本地调试相关的代码或者查看相关代码运 ...

  9. Jquery:小知识;

    Jquery:小知识: jQuery学习笔记(二):this相关问题及选择器   上一节的遗留问题,关于this的相关问题,先来解决一下. this的相关问题 this指代的是什么 这个应该是比较好理 ...

随机推荐

  1. 【python基础】第09回 数据类型内置方法 01

    本章内容概要 1.数据类型的内置方法简介 2.整型相关方法 3.浮点型相关方法 4.字符串相关方法 5.列表相关方法 本章内容详情 1.数据类型的内置方法简介 数据类型是用来记录事物状态的,而事物的状 ...

  2. Redis入门到精通01

    Redis入门到精通 目录 Redis入门到精通 一.Redis缓存框架基本介绍 1.1Redis的应用场景 二.Redis的安装方式 2.1Windows操作系统安装Redis 2.2Linux操作 ...

  3. ModuleNotFoundError: No module named 'distutils.spawn'

    解决办法: 安装python3-distutils sudo apt-get install python3-distutils

  4. Hash 哈希表和算法思路详解

    概述 哈希表是一种可以满足快速查找数据结构,时间复杂度接近O(1). 哈希函数是无限集到有限集的映射. 处理数据量大,查找效率要求高时推荐使用hash容器. 问题: 什么情况下考虑使用哈希容器? 常用 ...

  5. 阈值PSI代码

    阈值PSI 若交集数量超过某个给定阈值时,允许分布式的各个参与方在自己集合中找到交集,且除了交集外,得不到其他额外信息. 实现论文: Multi-Party Threshold Private Set ...

  6. 2022-7-9 html 第七组 刘昀航

    ​ 一.基础认知 1.1 认识网页 网页的组成: 文字.图片.音频.视频.超链接 网页背后的本质:前端程序员写的代码 前端的代码通过什么软件转换成用户眼中的页面:浏览器转化(解析和渲染) 1.2 5大 ...

  7. dos命令-*02

    1.cmd状态下 tab快速补充文件名 ↑↓快速填充之前输入的文件名 2.//这是Java的快速入门 //对代码的相关说明 //1.public class Hello 表示Hello是一个类,是一个 ...

  8. for_in循环练习题_100到999之间的水仙花数

    水仙花数 153 == 3**3 + 5**3 + 1**3 点击查看笔者代码 for i in range(100, 1000): a = i % 10 b = i // 100 c = (i // ...

  9. 倍增求RMQ

    RMQ,即区间最值查询,给定一个序列,求区间l-r的最大值.最小值. st表求RMQ,预处理On*logn,查询O1. 预处理: void init_rmq() { for(rll j=1;j< ...

  10. gotoscan:CMS指纹识别工具

    gotoscan 前言 项目地址 https://github.com/newbe3three/gotoscan 结合自己学习到的Go相关知识,通过实现这个简易的CMS指纹识别工具来锻炼一下自己写代码 ...