MasaFramework的MinimalAPI设计


在以前的MVC引用程序中,控制器负责接收输入信息、执行、编排操作并返回响应,它是一个功能齐全的框架,它提供了过滤器、内置了模型绑定与验证,并提供了很多可扩展的管道,但它偏重,不像其它语言是通过更加简洁的方式来开启Web之旅的,因此在.Net6.0官方引入了MinimalAPIs,即最小API,与MVC相比,它足够的简洁,适合小型服务来使用,下面就让我们看看如何使用MinimalAPI来开发一个web应用程序

入门

下面我们来看一下官方提供的MinimalAPI是如何使用的

  • 前提条件:安装.NET 6.0
  1. 新建ASP.NET Core 空项目Assignment.MinimalApiDemo
dotnet new web -o Assignment.MinimalApiDemo
cd Assignment.MinimalApiDemo
  1. 增加一个Get请求,修改Program
app.MapGet("/test", () => "Test Success!");

根据需求,自行增加Get (MapGet)、Post (MapPost)、Put (MapPut)、Delete (MapDelete)方法即可,完整代码如下:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/test", () => "Test Success!");

Masa版MinimalAPI

随着我们的服务变得越来越多,这些服务全部被堆积在Program中,这样岂不是变成流水账式的代码?那怎么做才能使得我们的代码更加美观呢?

下面我们就来看一下Masa提供的MinimalAPIs是如何来使用的

  1. 选中项目Assignment.MinimalApiDemo,并安装Masa.Contrib.Service.MinimalAPIs
dotnet add package Masa.Contrib.Service.MinimalAPIs --version 0.6.0-preview.13
  1. 注册Masa版的MinimalAPI,修改Program
var app = builder.AddServices();
  1. 新增加一个用户的服务,新增UserService
public class UserService : ServiceBase
{
    public IResult Add(RegisterUserRequest request)
    {
        //模拟添加用户
        return Results.Ok();
    }
}

到这里已经结束了,可能会有小伙伴十分的疑惑,Masa提供的方案让我有点摸不着头脑,但项目运行后就会发现在Swagger上多了一个服务

image.png

细心的小伙伴发现了,这个服务好像是我们新增的添加用户服务,但链接地址为什么是api/v1/Users ????

进阶

通过快速入门我们了解到如何使用MinimalAPI,但我们也清楚流水账式编程的危害,我们不希望让项目中充斥着流水账式的代码,我们希望它是整洁的,并且是有迹可循的,这时候Masa提供的MinimalAPI方案进入了我们的视野,它上手难度极低,对我们来说它是很棒的,但如果我们不清楚它是如何设计的话,我们敢放心大胆的使用它吗?虽然它有些枯燥,但我们必须要掌握它是如何设计的,它都支持了什么样的功能

约定

当服务未禁用自动映射路由时,框架会自动扫描继承ServiceBase的非抽象子类并注册到服务集合中(IServiceCollection),并为满足以下要求的方法自动注册路由

  • 当前类的方法的访问级别为public(不包含父类方法)
  • 方法上未增加特性IgnoreRouteAttribute

路由规则

路由规则优先级:

自定义路由 > 约定生成路由

  1. 如何自定义路由?

通过后续版本会增加支持

  • Builder.AddServices()又为什么必须要放到最后?

    我们知道通过builder.Build()可以得到WebApplication,但在.Net6.0中新增加了限制,这个限制就是在Build后无法再次更新IServiceCollection,否则会提示Cannot modify ServiceCollection after application is built

  • 为什么MinimalAPIs的生命周期是单例?

    目前AddServices方法中做了两件事,第一件事就是获取到所有的服务,并注册到服务集合中,第二件事就是触发服务并将对应服务的地址以及方法映射到到AppApp.Map类似App.Use,也是一个扩展方法,类似MVC的路由,其生命周期是单例,我们仅仅是将继承ServiceBase的服务映射到App中,并没有魔改MinimalAPI,因此并不存在性能问题,但同样其生命周期也无法改变

  • 总结

    MinimalAPIMVC我应该如何选择?

    小型服务使用MinimalAPI,因为它是很轻量级的,但如果是大型服务或者功能特别复杂的,还是推荐使用MVCMinimalAPI的上手成本很低,但它不是银弹,选择适合自己的才是最好的

    MinimalAPI还有一些特殊的地方,例如Get请求无法使用类对象来接收参数,如果希望使用类对象来接受,则需要使用自定义绑定,除此之外还有其他不一样的地方,完整文档可查看

    本章源码

    Assignment14

    https://github.com/zhenlei520/MasaFramework.Practice

    开源地址

    MASA.Framework:https://github.com/masastack/MASA.Framework

    MASA.EShop:https://github.com/masalabs/MASA.EShop

    MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor

    如果你对我们的 MASA Framework 感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们

    16373211753064.png