.NET 6,微软称为“最快的.NET”,带有了许多令人兴奋的新功能、语言和性能改进。这是自 .NET Core 3.1 以来的第一个 LTS 版本,将支持三年。

本次大版本发布,增加了一个新特性:Minimal APIs,这是什么技术?

        .NET6 使编写具有最小依赖性的 REST API 变得非常简单。

乍一看,Minimal APIs 似乎是微软对 NodeJS(使用 ExpressJS)HTTP 服务器的回应,它提供了最小的 API。

但是微软也对这项技术增加了几个关键词

  • LightWeight,Single file,Cloud Native API
  • Low ceremony,Top-Level C# programs
  • Easy to get started
  • Path to MVC

总结一句话:.NET 6 Minimal APIs 简化了HTTP Rest API的设计和实现,让开发者快速高效实现HTTP Rest API。

今天,我们花点时间,研究并科普一下.NET 6 Minimal APIs。

一、先看一下.NET 6 Minimal APIs的示例代码

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run();

在上面的示例中,app.MapGet 方法使用了内联 lambda 表达式,完成一个Controller Action的业务逻辑,真的是超简单。

超简单完成一个HTTP WebAPI的定义:不再有 Startup.cs、API 控制器、额外依赖项等。

只需要这 4 行代码即可生成以下输出:

二、探究一下这段代码背后的一些技术

上面的代码,微软官方文档上,建议大家使用VS2022,其实用VS Code也可以

Tutorial: Create a minimal web API with ASP.NET Core

但是本机得先安装.NET 6 SDK

安装完成后,打开VS Code,新建终端,创建一个Web Project

dotnet new web -o MyMinimalAPI

代码工程中,我们可以看到:

Program.cs这个类中没有using了,当然也没有main函数了,这里跟大家解释一下:

① .NET5 引入了Top-Level Class,可以没有main函数,代码作为直接入口执行

② .NET 6 新增了一个很棒的新特性——“隐式全局使用

自动生成不可见的 using 语句并在全局范围内声明它们,因此不必处理在每个文件中重复声明命名空间的混乱。

我们打开MyMinimalAPI.csproj 看看里面的内容,有一个配置:

       <ImplicitUsings>enable</ImplicitUsings>
 

dotnet build后,找到obj/Debug/net6.0 文件夹以查看隐藏的自动生成文件 - [ProjectName].GlobalUsings.g.cs。您可以定义一个单独的类来将所有 using 语句保存在一个地方。

这个功能,让我们不需要在每个文件中重复声明命名空间的using引用了。的确很方便、简单了。

当然,如果不想使用此功能,可以禁用 .csproj 文件中的ImplicitUsings标志。

在上面的示例中,app.MapGet 方法使用了内联 lambda 表达式。同时还提供了:

app.MapPost()
app.MapPut()
app.MapDelete()

接下来,我们用一个简单的示例,完成一个demo;

三、完成一个Minimal APIs完整的Demo

我们以一个简单Order订单为例,通过Minimal APIs实现CRUD设计和实现:

  3.1 先准备好Order类和IOrderService接口以及OrderServiceRepository

   Order类:    

namespace NET6
{
public class Order
{
public int ID {get;set;} public decimal Price {get;set;} public string CustomAddress {get;set;} public int State{get;set;}
}
}

IOrderService接口:

namespace NET6
{
public interface IOrderService
{
Order GetOrder(int id); void CreateOrder(Order order); void DeleteOrder(int id); void UpdateOrder(Order order);
}
}

OrderServiceRepository类,使用内存集合模拟实现数据存储层。

namespace NET6
{
public class OrderServiceRepository : IOrderService
{
static List<Order> orders = new List<Order>(); public Order GetOrder(int id)
{
return orders.FirstOrDefault(i=>i.ID == id)?? null;
} public void CreateOrder(Order order)
{
orders.Add(order);
} public void DeleteOrder(int id)
{
var order = orders.FirstOrDefault(i=>i.ID == id);
if(order!=null)
orders.Remove(order);
} public void UpdateOrder(Order order)
{
DeleteOrder(order.ID);
CreateOrder(order);
}
}
}

 3.2 在Program.cs类中,注册IOrderService服务,添加AddOrder和GetOrder Http Web API

using NET6;

var builder = WebApplication.CreateBuilder(args);

//registe IOrderService service
builder.Services.AddScoped<IOrderService, OrderServiceRepository>(); var app = builder.Build(); app.MapGet("/", () => "Hello World!"); //add order save API
app.MapPost("/add",(Order order,IOrderService service)=>
{
service.CreateOrder(order);
}).WithName("addorder"); //add order query API
app.MapGet("/getorder",(int id, IOrderService service)=>
{
return service.GetOrder(id);
}).WithName("getorder"); app.Run();

上面的低码中,首先增加一个文件级别的namespace,这个地方为了和大家示意Global Namespace的区别

   using NET6;
 
   然后,在ASP.NET DI依赖注入框架中添加IOrderService服务:
//registe IOrderService service
builder.Services.AddScoped<IOrderService, OrderServiceRepository>();

添加订单Order 保存API服务:

//add order save API
app.MapPost("/add",(Order order,IOrderService service)=>
{
service.CreateOrder(order);
}).WithName("addorder");

上面这个HttpWebAPI,我们采用了Post方式,请求是必须传入order参数。

这个代码中,我们看到保存订单方法有2个参数,一个是Order,另一个是IOrderService,第二个参数,原生支持依赖注入,不需要显式声明创建。

类似的,继续添加查询订单API服务

//add order query API
app.MapGet("/getorder",(int id, IOrderService service)=>
{
return service.GetOrder(id);
}).WithName("getorder");

 3.3 运行调试

在终端中输入dotnet run指令,启动运行调试

dotnet run

调试这3个API,建议大家使用PostMan工具

先说一个小坑,一开始使用PostMan工具调试保存订单接口,将order显式地参数放到Headers中请求,结果一直不通:

看了微软的示例文档后,建议直接将order json对象,http请求体中以raw的方式发起请求

其他的API接口则没有这个问题:

好了,以上是.NET 6 Minimal APIs的一些简单介绍和实践,希望能帮助大家。

周国庆

2022/2/28

通俗理解.NET 6 Minimal APIs的更多相关文章

  1. 通俗理解Android事件分发与消费机制

    深入:Android Touch事件传递机制全面解析(从WMS到View树) 通俗理解Android事件分发与消费机制 说起Android滑动冲突,是个很常见的场景,比如SliddingMenu与Li ...

  2. Effective Java通俗理解(持续更新)

    这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...

  3. Effective Java通俗理解(下)

    Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...

  4. 关于MySQL中的自联结的通俗理解

    关于MySQL中的自联结的通俗理解 前言:最近在通过SQL必知必会这本书学习MySQL的基本使用,在学习中也或多或少遇到了点问题,我也正好分享给大家,我的这篇博客用到的所有表格的代码都是来自SQL必知 ...

  5. Effective Java通俗理解(上)

    这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...

  6. OSI七层模式简单通俗理解

    OSI七层模式简单通俗理解 这个模型学了好多次,总是记不住.今天又看了一遍,发现用历史推演的角度去看问题会更有逻辑,更好记.本文不一定严谨,可能有错漏,主要是抛砖引玉,帮助记性不好的人.总体来说,OS ...

  7. 通俗理解决策树中的熵&条件熵&信息增益

    参考通俗理解决策树算法中的信息增益 说到决策树就要知道如下概念: 熵:表示一个随机变量的复杂性或者不确定性. 假如双十一我要剁手买一件衣服,但是我一直犹豫着要不要买,我决定买这件事的不确定性(熵)为2 ...

  8. CNN笔记:通俗理解卷积神经网络【转】

    本文转载自:https://blog.csdn.net/v_july_v/article/details/51812459 通俗理解卷积神经网络(cs231n与5月dl班课程笔记) 1 前言 2012 ...

  9. 通俗理解LDA主题模型

    通俗理解LDA主题模型 0 前言 印象中,最開始听说"LDA"这个名词,是缘于rickjin在2013年3月写的一个LDA科普系列,叫LDA数学八卦,我当时一直想看来着,记得还打印 ...

随机推荐

  1. 局域网内部怎么安全接入U盘?

    准备工具: 内部专用U盘一个: 能连接外网的电脑(暂称"安全机")一个. 第一.安全机上安装360杀毒.360安全卫士或其它安全软件.并经常更新病毒库.木马库. 第二.外来U盘先通 ...

  2. 解决new Thread().Start导致高并发CPU 100%的问题

    背景 之前接手一个项目的时候,发现到处是 new Thread(()=>{ //do something }).Start(); 这么做的目的,无非是为了减少页面等待时间提高用户体验,把一些浪费 ...

  3. C++多线程之可重入锁

    #include<iostream> #include<thread> #include<mutex> using namespace std; recursive ...

  4. gorm中的基本查询

    检索单个对象 GORM 提供了 First.Take.Last 方法,以便从数据库中检索单个对象.当查询数据库时它添加了 LIMIT 1 条件 // 获取第一条记录(主键升序) db.First(&a ...

  5. golang中结构体中的嵌套

    package main import "fmt" type Base struct { name string } func (b *Base) m1() int { retur ...

  6. IDEA设置Maven

    1,在idea中设置maven,让idea和maven结合使用 idea中内置了maven,一般不使用内置,因为用内置修改maven的设置不方便 使用自己安装的maven,需要覆盖idea中默认的设置 ...

  7. 使用Hot Chocolate和.NET 6构建GraphQL应用(3) —— 实现Query基础功能

    系列导航 使用Hot Chocolate和.NET 6构建GraphQL应用文章索引 需求 在本文中,我们通过一个简单的例子来看一下如何实现一个最简单的GraphQL的接口. 实现 引入Hot Cho ...

  8. K8S SVC 转发原理

    在前面的文章中,我们已经多次使用到了 Service 这个 Kubernetes 里重要的服务对象.而 Kubernetes 之所以需要 Service,一方面是因为 Pod 的 IP 不是固定的,另 ...

  9. node.js request请求url错误:证书已过期 Error: certificate has expired

    场景: node:8.9.3版本 报错代码: Error: certificate has expired at TLSSocket.<anonymous> (_tls_wrap.js:1 ...

  10. Vue3源码分析之Diff算法

    Diff 算法源码(结合源码写的简易版本) 备注:文章后面有详细解析,先简单浏览一遍整体代码,更容易阅读 // Vue3 中的 diff 算法 // 模拟节点 const { oldVirtualDo ...