【ASP.NET Core】体验一下 Mini Web API
在上一篇水文中,老周给大伙伴们简单演示了通过 Socket 编程的方式控制 MPD (在树莓派上)。按照计划,老周还想给大伙伴们演示一下使用 Web API 来封装对 MPD 控制。思路很 Easy,树莓派上使用本地 Socket 来封装一下,然后以 Web API 的方式对客户端公开。这样有一个好处:之后不管你打算把客户端做成桌面窗口,还是 Web 页面,或是做成手机 App,你都可以直接调用这套 Web API。这样一来,很多代码就不必重复写了,省时省力,减少脑细胞的大量死亡。
如果大家比较关心时事的话,应该知道 .NET 6 的 ASP.NET Core 有一个新特性—— Mini API,或 Mini Web API。有一个不错的翻译叫做“极简 API”。其实,极简的不只是 Web API,整个 ASP.NET Core 应用项目的结构都精简了不少。最让老周高兴的就是没有了 Startup 类(其实早期版本中也可以不使用 Startup,如果你以前看过老周的误人子弟教程的话,你应该有印象),也不用费心地搞个什么 ConfigureService 又要弄个 Configure 方法约定了。再配合 C# 9 的新功能,连 Main 方法都省了。所以初始化配置工作都可以在一个代码文件中搞定。
使用这个简化版的 Web API 来做 MPD 的封装还真的不错。不过,本文老周先不弄这个,先让大伙伴们了解一下 Mini API 怎么玩——权且当作预备知识。
.NET 6 还有个新功能也不错,就是全局的 using 指令。以前在 C 语言中,如果你写一个 abc.h 头文件,里面放上这些代码:
#ifndef _ABC_H_
#define _ABC_H_ #include "nc.h"
#include "nt.h"
#include "zz.h"
#include "xb.h"
#include "sb.h" #endif
然后在代码文件中 include 一个这个 abc.h 就可以间接引用这些头文件,但 C# 中没有这种玩法,每个代码文件要用到哪些命名空间,都要写一遍 using 指令。在随同 .NET 6 一同发布的 C# 10 中终于有全局 using 了。只要你在其中一个代码文件中写上全局 using 指令,然后其他代码文件中就不必再 using 了。
方法是在 using 前加上 global 就行了。C# 虽然早有 global 关键字,但在过去这个并不是全局 using 用的,而是专用来标识 .NET 框架中的命名空间的,主要是防止命名空间重名的。
好了,咱们现在就去嗨一下 Mini API吧。
此处假设你已经安装好 VS 2022 和 .NET 6。在创建新项目时选择空白 ASP.NET Core 应用程序。用空白项目方便稍后写自己的 Code。

然后输入项目名称以及存放路径。

选择.net 版本号。

最后,确定新创建项目。
---------------------------------------------------------------------------------
项目创建后你会发现,真TM简洁了不少,Program.cs 文件中只有这么几行。
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run();
第一行:调用 CreateBuilder 方法创建一个builder ,这个 builder 随后用于构建 Web 应用程序。
第二行:直接就用预设的参数构建了一个 app 对象。
第三行:配置 HTTP 管道——怎么处理HTTP请求。此处配置表明只向客户端返回“Hello World!”。
第四行:运行 app。
你,不用再写 Startup 类了,也不用遵守方法签约定去写 ConfigureServices 等方法了。
要配置服务咋办?直接 Services Add。例如
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddRazorPages();
builder.Services.AddAntiforgery()
.AddWebEncoders()
.AddSingleton<XXX, YYY>();
var app = builder.Build();
app.MapGet("/", () => "Hello World!"); app.Run();
看看是不是很整齐?注意这个过程是在 build 方法调用之前完成的。原因和以前 Startup 类中写方法一样,Add 服务是声明咱们的应用程序中要使用哪些功能,哪些对象被用于依赖注入,一旦 build 了,程序的功能结构就确定下来了,所以应用程序构建后就不再修改其功能了。
以前在写 Startup 时,我们知道,还有一个 Configure 方法用来配置中间件的,也就是刚刚说的配置HTTP管道。build 方法构建 app 后,就可以直接通过这个 app 实例来配置你要 Use 的东西。例如
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// 中间件配置
app.MapGet("/", () => "Hello World!");
app.UseRouting();
app.UseCookiePolicy();
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Server", "Big Bomb");
await next();
});
app.MapControllers();
app.MapBlazorHub();
app.MapRazorPages();
app.Run();
如果我们要编写 Mini API,不需要 Add 什么 Service,也不需要 Use 什么组件,在 build 和 app.run 之间直接 MapXXX 就行了。XXX 指 HTTP 请求方法,比如 GET、POST、PUT 等。
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
//====================================
// Mini API 写在这里
//====================================
app.Run();
相当有意思的是:这些 MapXXX 扩展方法都有一个 handler 参数,类型是 Delegate。也就是说你在调用时可以传递任何类型的委托对象。于是,就可以这样搞:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build(); app.UseHttpsRedirection();
//====================================
// Mini API 写在这里
app.MapGet("/greet", () =>
{
return "What the fuck?";
});
//====================================
app.Run();
一个 Web API 就完成了。真的,可以用了,不信运行下看看。拿出秘密武器——Postman,测试一下。

用 Postman 还是有些不够爽,而且这货现在越做越复杂,还整天叫你注册帐号,实属无趣。我们改为用 swagger 来测试。打开 Nuget 包管理器,搜索 swagger。

安装这个包包。
把代码改一下。
var builder = WebApplication.CreateBuilder(args);
// 不要忘了加这两个服务
builder.Services.AddSwaggerGen();
builder.Services.AddEndpointsApiExplorer();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
//====================================
// Mini API 写在这里
app.MapGet("/greet", () =>
{
return "What the fuck?";
});
//====================================
app.Run();
这样一来,咱们在开发测试阶段就可以直接用这个组件在 Web 页上测试 API 的调用了,不再启动其他工具软件了。
运行该项目,然后浏览器定位到 http(s)://root_url:port/swagger。
比如,我运行后得到的URL是 https://localhost:7189,那么在浏览器中打开 https://localhost:7189/swagger。

点击右边的“try it out”,然后点 “Execute” 按钮,就能看到执行结果了。

怎么样,好用吧?咱们再添加一个API,这次要带参数的 POST 请求。
app.MapPost("/submit", (string name, int age) =>
{
return $"你提交的内容:{name} - {age}";
});
这个 API 带两个参数,分别取名为 name,age。在调用时,是通过请求的 body 来提供的,格式为 JSON。
前面老周说过,这些MapXXX方法的委托参数是 Delegate 类型,所以你可以用任意类型的委托,有参数的没参数的,有返回值的没返回值的。
每次调试时都要在浏览器地址输入 http(s)://root/swagger 太TM不方便了,咱们可以配置一下,让其自动定位到 swagger 下。打开项目属性窗口,转到“调试”标签。

点击页面上的“打开调试启动配置文件 UI”链接。

把滚动条往地狱方向拉,一直拉到看到“URL”标题,在文本中填上 swagger。搞定。
现在,你直接运行项目,就自动打开 API 列表了。点击展开 submit,再点“try it out”。

为 name 和 age 参数填上值,执行。

下面再举一例,请求方式为 GET,参数来自 URL 查询(即带 ? 的URL,如 /abc?t=3000)。
app.MapGet("/md5", ([FromQuery(Name = "msg")] string data) =>
{
byte[] buffer = Encoding.UTF8.GetBytes(data);
using MD5 md5ec = MD5.Create();
byte[] comres = md5ec.ComputeHash(buffer);
return $"加密结果:{Convert.ToHexString(comres).ToLower()}";
});
这个 API 的功能:接收一个字符串类型的对象,对其作 MD5 运算,然后返回结果。这个请求是从查询字符串中得到参数 data 的值的,所以要加上 FromQuery 特性,而且,实际传值时查询参数的名称与API的参数名称不同,故要用 Name = .... 明确指定,要从 msg 查询参数中提取值。
综上,此API的调用方式为 GET /md5?msg=呵呵哈哈呵呵哈。

咱们玩这一步了,你心中一定有个高大上的疑问:这货支持依赖注入乎?
很好,老周也有此疑问,要不,咱们搞搞看。
public interface IComputer
{
int RunIt(int x, int y, int z);
} internal class ComputerService : IComputer
{
public int RunIt(int x, int y, int z)
{
return x - y - z;
}
}
我定义了一个服务接口,里面有个 RunIt 方法;然后俺实现之。逻辑很简单,x、y、z 三数相减。
接下来改代码,在 build 方法调用之前注册服务,咱们就注册个单实例模式吧,全局共享一个实例。
var builder = WebApplication.CreateBuilder(args);
……
builder.Services.AddSingleton<IComputer, ComputerService>();
然后,我们完成 API。
app.MapPost("/comp", (int n1, int n2, int n3, IComputer compsv) =>
{
int r = compsv.RunIt(n1, n2, n3);
return $"计算结果:{r}";
});
不要犹豫,运行它!

得到结果:

在这个API中,n1,n2,n3 三个参数是从客户端 POST 过来的,而最后一个参数是通过依赖注入得到引用对象的。那么,把参数的位置调换一下,是否也可行呢?
app.MapPost("/comp", (IComputer compsv, int n1, int n2, int n3) =>
{
int r = compsv.RunIt(n1, n2, n3);
return $"计算结果:{r}";
});
然后再测,结果表明,是可行滴。

好了,今天的话题就聊到这儿了,下次咱们就用这个 Mini API 来封装 MPD。
【ASP.NET Core】体验一下 Mini Web API的更多相关文章
- 002.Create a web API with ASP.NET Core MVC and Visual Studio for Windows -- 【在windows上用vs与asp.net core mvc 创建一个 web api 程序】
Create a web API with ASP.NET Core MVC and Visual Studio for Windows 在windows上用vs与asp.net core mvc 创 ...
- ASP.NET Core MVC中构建Web API
在ASP.NET CORE MVC中,Web API是其中一个功能子集,可以直接使用MVC的特性及路由等功能. 在成功构建 ASP.NET CORE MVC项目之后,选中解决方案,先填加一个API的文 ...
- ASP.NET Core 1.0开发Web API程序
.NET Core版本:1.0.0-rc2Visual Studio版本:Microsoft Visual Studio Community 2015 Update 2开发及运行平台:Windows ...
- 【asp.net core】实现动态 Web API
序言: 远程工作已经一个月了,最近也算是比较闲,每天早上起床打个卡,快速弄完当天要做的工作之后就快乐摸鱼去了.之前在用 ABP 框架(旧版)的时候就觉得应用服务层写起来真的爽,为什么实现了个 IApp ...
- 【ASP.NET Core】从向 Web API 提交纯文本内容谈起
前些时日,老周在升级“华南闲肾回收登记平台”时,为了扩展业务,尤其是允许其他开发人员在其他平台向本系统提交有关肾的介绍资料,于是就为该系统增加了几个 Web API. 其中,有关肾的介绍采用纯文本方式 ...
- ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了
引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必是件很痛苦的事情吧,但文档又必须写,而且文档的格式如果没有具体要求的话,最终完成的文档则完全取决于开发者 ...
- ASP.NET Core WebApi使用Swagger生成api
引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必是件很痛苦的事情吧,但文档又必须写,而且文档的格式如果没有具体要求的话,最终完成的文档则完全取决于开发者 ...
- 【转】ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了
原文链接:https://www.cnblogs.com/yilezhu/p/9241261.html 引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必 ...
- ASP.NET Core WebApi使用Swagger生成api说明文档
1. Swagger是什么? Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件 ...
随机推荐
- 1.1 jvm核心类加载器--jdk源码剖析
目录 前提: 运行环境 1. 类加载的过程 1.1 类加载器初始化的过程 1.2 类加载的过程 1.3 类的懒加载 2. jvm核心类加载器 3. 双亲委派机制 4. 自定义类加载器 5. tomca ...
- Linux安装配置Java
先从 Oracle 官网下载 Java 运行 tar -zxvf xxxx.tar.gz 指令将 Java 解压到 /usr/local/java 下(个人习惯,无所谓) 修改环境变量 vim /et ...
- 1-基本建表sql语句
基本的建表语句的总结 --建表语法 CREATE TABLE 表名( --约束可以没有 列名1 数据类型 [约束], 列名2 数据类型 [约束], ......, [约束], ..... ); --该 ...
- 阿里云研究员叔同:Serverless 正当时!
作者 | 叔同 导读:Serverless 将开发人员从繁重的手动资源管理和性能优化中解放出来,就像数十年前汇编语言演变到高级语言的过程一样,云计算生产力再一次发生变革.Serverless 的核心价 ...
- .Net Core with 微服务 - 使用 AgileDT 快速实现基于可靠消息的分布式事务
前面对于分布式事务也讲了好几篇了(可靠消息最终一致性 分布式事务 - TCC 分布式事务 - 2PC.3PC),但是还没有实战过.那么本篇我们就来演示下如何在 .NET 环境下实现一个基于可靠消息的分 ...
- linux 信号与处理
一.linux信号是什么 基本概念 信号是事件发生时对进程的通知机制,也就是所谓的软件中断.信号和硬件的中断类似,是软件层对中断机制的模拟,在多数情况下是无法预测信号产生的时间,所以软件层提供了一种处 ...
- 洛谷3320 SDOI2015寻宝游戏(set+dfs序)(反向迭代器的注意事项!)
被\(STL\)坑害了一个晚上,真的菜的没救了啊. 准确的说是一个叫\(reverse\ iterator\)的东西,就是我们经常用的\(rbegin()\) 有一个非常重要的性质 在反向迭代器中,+ ...
- vj-2021.6.5-补题
B - B 内容: One day, as Sherlock Holmes was tracking down one very important criminal, he found a wond ...
- scala基础篇 源码中 :_*的作用
在scala源码中有大量的:_*,其作用是把Array.list转换为参数列表,作为变长参数传入参数列表 例子: def sumx(a:Int*)={ a.sum } val a=Range(1,9) ...
- Java/JDK/J2SE
Java8与JDK1.8与JDK8与J2SE8与J2SE1.8的区别是什么? Java是面向对象的编程语言,在我们开发Java应用的程序员的专业术语里,Java这个单词其实指的是Java开发工具,也就 ...