Minimal API 是 .NET 6 提供的最新功能 , 对比传统的 http://ASP.NET Core Web API 方式更加直接 , 你可以用几行代码编写好 REST API 。没有了祖传的 Startup.cs 和 Controller ,通过简单的代码就可以完成 API 的开发。在第二阶段的 .NET 挑战赛中就以 .NET 6 中 的 Minimal API 作为学习的主线来完成相关的云原生应用。有小伙伴问怎么可以用好 Minimal API ,如何去架构一个 Minimal API 的云原生解决方案 ,下面我和大家说说 。
再来认识一下 Minimal API
文章图片
对比起传统的 Web API , Minimal API 取消了 Controller , 文件的组织方式更像 Node.js . 在以前要启动一个 Web API , .NET 对比起 JavaScript , Go , Rust , Python 等语言的 Web 框架还是相对复杂的。.NET 团队希望通过 Minimal API 简化 .NET Web 框架 ,让开发者能在一个文件完成简单 API 构建。以下是一个最基本的 Minimal API 项目。
文章图片
MapGet 是 EndpointRouteBuilderExtensions 类的扩展方法, 你可以看到它设定了路由规则后, 会传递一个委托参数 , 编译器会将它转换为 RequestDelegate ,通过它来取代 Controller 的工作。然后使用 app.Run() 方法来运行我们的 Minimal API 应用程序。
架构 .NET 6 Minimal API 项目
在传统的 Web API 通过 Controller ,针对不同的功能进行 CRUD 的开发, 但如果我们是 Minimal API 呢 , 要如何组织呢 ?还有我们是否还能用 Repository Pattern 呢 ?
- Controller 再见
文章图片
如上图 ,是我画的一个图 ,通过把 Course 和 Book 划分为两个 Module , 在 Module 里都包含了路由的设置 。这个时候我们做一个接口 ,因为每个 Module 都需要包含添加路由的方法,所以把它做成一个接口 IBaseModule ,以后不同的 Module 都可以用 。
文章图片
如何添加进去 Program.cs ? 我们来用一个 IEndpointRouteBuilder 的扩展方法 ,把路由添加都归类进来
public static class ModuleExtensions
{
?
public static void Routers(this IEndpointRouteBuilder builder)
{
?
CourseModule courseModule = new CourseModule();
BookModule bookModule = new BookModule();
courseModule.AddModuleRoutes(builder);
bookModule.AddModuleRoutes(builder);
?
?
}
}
这里有一个技巧就是我们可以通过以下 typeof 找到继承于 IBaseModule 的 Module 并将它实例化后调用添加路由的方法。
public static void Routers(this IEndpointRouteBuilder builder)
{
?
var modules = typeof(IBaseModule).Assembly
.GetTypes()
.Where(p => p.IsClass && p.IsAssignableTo(typeof(IBaseModule)))
.Select(Activator.CreateInstance)
.Cast();
?
foreach(var module in modules)
{
module.AddModuleRoutes(builder);
}
?
}
- Repostitory 模式能延续吗 ?
文章图片
在 Minimal API 使用 Repository Pattern 在整体上和传统的 http://ASP.NET MVC 没有不同 ,这里是我用 Repository 模式架构的 Minimal API 的截图
文章图片
注意一点有人认为 Repository 模式有点过时 ,和过度架构 , 但我觉得还是非常有必要的,因为这样可以更好管理你的项目。
- 依赖注入
public static class ModuleExtensions
{
?
static readonly List moduleList = new List();
?
private static IEnumerable GetModules()
{var modules = typeof(IBaseModule).Assembly
.GetTypes()
.Where(p => p.IsClass && p.IsAssignableTo(typeof(IBaseModule)))
.Select(Activator.CreateInstance)
.Cast();
?
return modules;
}
?
public static void Routers(this IEndpointRouteBuilder builder)
{
?
foreach(var module in moduleList)
{
module.AddModuleRoutes(builder);
}
?
}
?
public static void AddIoC(this IServiceCollection services)
{
?
foreach(var module in GetModules())
{
module.AddModuleIoC(services);
moduleList.Add(module);
}
?
}
?
public static void AddGlobalConfig(this IServiceCollection services)
{
services.AddScoped();
services.AddScoped();
}
?
}
注意一些地方 , 虽然在 Minimal API 上 ,我们的依赖注入虽然把不同的Services 注册了单例给 RequestDelegate 所调用 , 但在作为参数传送时,要添加 [FromServices] 属性标签才有效 , 如下
app.MapGet("/Course/GetCourse" ,([FromServices] ICourseService courseService , int typeID)=> {returncourseService.GetCourseList(typeID);
});
Minimal API or Web API 在 http://ASP.NET Core 中开发 API 时,你 90% 都在使用 http://ASP.NET Core MVC。而当你使用 http://ASP.NET Core MVC 架构 Web API 时 , 你会发现有点复杂 , 你需要符合 http://ASP.NET Core MVC 的所有要求 。而 Minimal API 正好解决了这些问题 , 特别对于一些只做 API 或者 入门的开发者, 只需要简洁的代码就能完成类似 Node.js 一样的工作 。有人问我 Minimal API 会取代传统的 Web API 吗 ?我可以告诉大家不会。还是那句话 , 选择符合项目需求的方法才是正道的。
小 结 在云原生的年代 , Minimal API 是 .NET 的又一把利器 。.NET 6 的 Minimal API 要用好 ,实际上还是用到不少旧知识,像 Module 的构建方式,我参考了开源的 Carter , 像 Repository 模式还是没有变 ,当然还是那些熟悉的语法 C# , 这就是我们常说的 ”万变不离其中“ 。Minimal API 不是要取代 Web API , 更多是给开发人员多一个选择 。作为 .NET 学习挑战赛知识点的补充 , 希望能给各位小伙伴更深刻了解 Minimal API 在实际应用场景的技巧 。本次的示例代码也放到我的 GitHub 上了 ,如果各位小伙伴感兴趣可以访问该链接获取完整的代码。
相关资源
- 学习 Minimal API , 请访问该链接
https://docs.microsoft.com/zh... - 学习 Repository 模式 , 请访问该链接
https://docs.microsoft.com/zh...
文章图片
长按识别二维码
关注微软中国MSDN