当前位置 博文首页 > 文章内容

    .Net Minimal API 介绍

    作者:shunshunshun18 栏目:未分类 时间:2021-12-28 14:32:11

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    Minimal APIs 是.Net 6 中新增的模板,借助 C# 10 的一些特性以最少的代码运行一个 Web 服务。本文脱离 VS 通过 VS Code,完成一个简单的 Minimal Api 项目的开发。

    创建项目

    新建一个文件夹,用来管理我们的项目文件,文件夹内启动命令行,通过dotnet new web创建项目。

    Minimal
    ├── obj
    ├── Properties
    ├── appsettings.Development.json
    ├── appsettings.json
    ├── Minimal.csproj
    └── Program.cs
    

    运行项目

    项目目录下执行dotnet run,运行项目。

    PS C:\Users\User01\Desktop\Minimal> dotnet run
    正在生成...
    info: Microsoft.Hosting.Lifetime[14]
          Now listening on: https://localhost:7221
    info: Microsoft.Hosting.Lifetime[14]
          Now listening on: http://localhost:5252
    info: Microsoft.Hosting.Lifetime[0]
          Application started. Press Ctrl+C to shut down.
    info: Microsoft.Hosting.Lifetime[0]
          Hosting environment: Development
    info: Microsoft.Hosting.Lifetime[0]
          Content root path: C:\Users\User01\Desktop\Minimal\
    

    运行效果如下:

    run

    Coding

    builder 实例提供了 Services 属性,可以完成原本 Startup 类 ConfigureServices 方法中注册服务的工作,Configure 方法的一些 Use 操作则通过 app 来完成。

    builder.Services.AddMemoryCache();
    
    app.UseStaticFiles();
    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", $"{builder.Environment.ApplicationName} v1"));
    }
    

    Map

    builder.Build()返回的 app 实例提供了 Map、Methods、MapXXX 方法实现 HttpMethod 路由的映射。
    这里只以 Get 请求为例。Map 和 MapMethods 方法提供不同的特性和参数可以代替 MapGet 方法。

    app.MapGet("/", () => "Hello World!");
    
    app.Map("/", [HttpGet] () => "Hello World!");
    

    HttpGet 特性限定请求为 Get 请求,如果不指定则不限制请求方法,Get、Post 等方式可以请求改路由地址

    app.MapMethods("/", new List<string>() { HttpMethod.Get.ToString() }, () => "Hello World!");
    

    Application

    代码内直接修改应用程序配置,如修改监听端口

    app.Urls.Add("http://localhost:3000");
    //app.Run();
    app.Run("http://localhost:4000");
    

    优先级 app.Run > app.Urls.Add > launchSettings

    Dependency Injection

    Minimal APIs 中无法使用构造函数注入,但可以通过参数方式注入并忽略 FromServices 特性。

    app.MapGet("/info", (IWebHostEnvironment env) => new {
        Time = DateTimeOffset.UtcNow,
        env.EnvironmentName
    });
    

    Context

    一些 Http 请求的上下文信息也可以通过参数直接指定,方法体内直接使用,代替 MVC 中的 Request 等。如:

    • HttpContext
    • HttpRequest
    • HttpResponse
    • ClaimsPrincipal
    • CancellationToken
    app.MapGet("/context", (HttpContext httpContext) => new
    {
        Data = httpContext.Connection.Id
    });
    

    更多类型参考:github

    Responses

    通过静态类 Results 返回标准的相应类型,实现和 ControllerBase 提供对应方法相同的效果。

    app.MapGet("/ok/{id}", (int id) =>
    {
        return Results.Ok($"ok:{id}");
    });
    

    Link Generation

    通过扩展方法 WithXXX 等可以对路由进行一些配置,如通过 WithName 指定名称,再通过 LinkGenerator 生产对应 Uri,避免硬编码

    app.MapGet("/context", (HttpContext httpContext) => new
    {
        Data = httpContext.Connection.Id
    }).WithName("hi");
    
    app.MapGet("hello", (LinkGenerator linker) =>
            $"The link to the hello route is {linker.GetPathByName("hi", values: null)}");
    

    除了 WithXXX 等一些列 RoutingEndpointConvention 扩展方法外,还提供了 AuthorizationEndpointConvention 相关扩展方法 RequireAuthorization、AllowAnonymous 代替 MVC 模式中的相关特性(特性也还可以用只是多了一个支持方式)。

    本文只列出 Minimal APIs 的一些简单用法,集成 Swagger 等用法内容参考:https://minimal-apis.github.io/hello-minimal/

    接口的返回状态码和类型等可以通过扩展方法 Produces 说明,如:Produces(contentType:"application/xml"); ,但是接口备注貌似还不支持,我尝试了很多方式都不能正确显示。

    Code Format

    Minimal APIs 上面示例存在的问题是 Program 文件中会有太多的编码,所有路由的映射和响应都在一起,虽然可以通过如下方式使用静态方法抽离响应方法,但所有的 Route Map 还是列在一起,不能像 Controller 一样分离。

    var handler = new HelloHandler();
    
    app.MapGet("/", handler.Hello);
    
    class HelloHandler
    {
        public string Hello()
        {
            return "Hello World";
        }
    }
    

    可以借助开源框架 MASA.Contrib提供的 MASA.Contrib.Service.MinimalAPIs 完成代码封装。

    详细用法参考 MASA.EShop

    Program.cs

    var builder = WebApplication.CreateBuilder(args);
    var app = builder.Services.AddServices(builder);
    app.Run();
    

    HelloService.cs

    public class HelloService : ServiceBase
    {
        public HelloService(IServiceCollection services): base(services) =>
            App.MapGet("/api/v1/helloworld", ()=>"Hello World"));
    }
    
    

    我们正在行动,新的框架、新的生态

    我们的目标是自由的易用的可塑性强的功能丰富的健壮的

    所以我们借鉴Building blocks的设计理念,正在做一个新的框架MASA Framework,它有哪些特点呢?

    • 原生支持Dapr,且允许将Dapr替换成传统通信方式
    • 架构不限,单体应用、SOA、微服务都支持
    • 支持.Net原生框架,降低学习负担,除特定领域必须引入的概念,坚持不造新轮子
    • 丰富的生态支持,除了框架以外还有组件库、权限中心、配置中心、故障排查中心、报警中心等一系列产品
    • 核心代码库的单元测试覆盖率90%+
    • 开源、免费、社区驱动
    • 还有什么?我们在等你,一起来讨论

    经过几个月的生产项目实践,已完成POC,目前正在把之前的积累重构到新的开源项目中

    目前源码已开始同步到Github(文档站点在规划中,会慢慢完善起来):

    MASA.BuildingBlocks

    MASA.Contrib

    MASA.Utils

    MASA.EShop

    BlazorComponent

    MASA.Blazor

    QQ群:7424099

    微信群:加技术运营微信(MasaStackTechOps),备注来意,邀请进群

    masa_stack_tech_ops.png

    ​ ------ END ------

    作者简介

    马跃:MASA技术团队成员。

    bkbky