5.1 动态 WebAPI
📝 模块更新日志
-
新特性
查看变化
在一些特定的需求中,我们需要在运行时动态编译代码,如动态编写 WebAPI
,之后能够在不重启主机服务的情况下即可有效。比如这里动态添加 SomeClass
动态 WebAPI
,然后在 Swagger/路由系统
中立即有效:
using Furion;
using Furion.DynamicApiController;
using Microsoft.AspNetCore.Mvc;
namespace YourProject.Application;
public class PluginApiServices : IDynamicApiController
{
private readonly IDynamicApiRuntimeChangeProvider _provider;
public PluginApiServices(IDynamicApiRuntimeChangeProvider provider)
{
_provider = provider;
}
/// <summary>
/// 动态添加 WebAPI/Controller
/// </summary>
/// <param name="csharpCode"></param>
/// <param name="assemblyName">可自行指定程序集名称</param>
/// <returns></returns>
public string Compile([FromBody] string csharpCode, [FromQuery] string assemblyName = default)
{
// 编译 C# 代码并返回动态程序集
var dynamicAssembly = App.CompileCSharpClassCode(csharpCode, assemblyName);
// 将程序集添加进动态 WebAPI 应用部件
_provider.AddAssembliesWithNotifyChanges(dynamicAssembly);
// 返回动态程序集名称
return dynamicAssembly.GetName().Name;
}
/// <summary>
/// 移除动态程序集 WebAPI/Controller
/// </summary>
public void Remove(string assemblyName)
{
_provider.RemoveAssembliesWithNotifyChanges(assemblyName);
}
}
这时只需要请求 api/plugin-api/compile
接口同时设置请求 Content-Type
为 text/plain
,接下来传入 C# 代码字符串
即可,如:
using Furion.DynamicApiController;
namespace YourProject.Application;
public class SomeClass : IDynamicApiController
{
public string GetName()
{
return nameof(Furion);
}
}
之后刷新浏览器即可看到最新的 API
:
还可以在运行时动态卸载,使用 DELETE
请求 api/plugin-api
即可。
-
- 动态
WebAPI
自动检查路由是否包含重复参数,如果有自动修正而不是抛异常 4.8.6.5 ⏱️2023.02.17 5f15ea1
- 动态
查看变化
在 Furion 4.8.6.5
之前,下列代码会抛出异常:The route parameter name 'roleid' appears more than one time in the route template.
原因是生成的路由包含了多个 {roleId}
:/api/with-class/system/role/deptTree/{roleId}/{roleId}
。
public class WithClass : IDynamicApiController
{
[HttpGet("system/role/deptTree/{roleId}")] // 过去版本抛异常,Furion 4.8.6.5+ 正常~
public string GetResult2(string roleId)
{
return nameof(Furion);
}
}
新版本 Furion 4.8.6.5+
修正了该错误,自动移除后面重复的路由参数且不再抛异常,也就是最终生成路由为:/api/with-class/system/role/deptTree/{roleId}
-
- 动态
WebAPI
支持[RouteConstraint(":*")]
路由约束 4.8.6.2 ⏱️2023.02.10 #I6E6JA
- 动态
-
- 动态
WebAPI
支持更加强大的路由组合功能 4.8.5.7 ⏱️2023.02.03 #I6CLPT
- 动态
查看变化
using Furion.DynamicApiController;
using Microsoft.AspNetCore.Mvc;
namespace WebApplication38;
[Route("api/[controller]")]
[Route("api2/[controller]")]
public class Test1Service : IDynamicApiController
{
[HttpGet("test")]
[HttpPost]
[AcceptVerbs("PUT", "PATCH")]
public async Task GetTestName()
{
await Task.CompletedTask;
}
}
public class Test2Service : IDynamicApiController
{
[HttpGet("/root/test")]
[HttpGet("test")]
[HttpGet(Name = "other-test")]
[HttpGet("template-test", Name = "other-test")]
[HttpPost]
[AcceptVerbs("PUT", "PATCH")]
public async Task GetTestName()
{
await Task.CompletedTask;
}
}
[Route("api/[controller]")]
[Route("api2/[controller]/second")]
[Route("api3/[controller]/three")]
public class Test3Service : IDynamicApiController
{
[HttpGet]
[HttpGet("get/[action]")]
[HttpPost]
[HttpPost("post/cus-version")]
public string GetVersion()
{
return "1.0.0";
}
}
-
突破性变化
- 动态
WebAPI
生成路由[HttpMethod(template)]
规则 4.8.5.7 ⏱️2023.02.03 #I6CLPT
- 动态
查看变化
在过去,TestMethod
生成路由为:/mytest
// 注意这里没有 [Route] 特性
public class ClassService: IDynamicApiController
{
[HttpPost("mytest")]
public void TestMethod()
{
}
}
新版本:TestMethod
生成路由为:/api/class/mytest
,TestMethod2
生成路由为:/mytest
。
// 注意这里没有 [Route] 特性
public class ClassService: IDynamicApiController
{
[HttpPost("mytest")]
public void TestMethod()
{
}
[HttpPost("/mytest")]
public void TestMethod2()
{
}
}
也就是新版本如果不需要自动添加前缀,需在前面添加 /
,旧版本不需要。
-
问题修复
查看变化
过去版本生成错误重复路由,如:api/system/SystemDictionary/api/system/SystemDictionary/Add
,现已修正。
public class WithClass : IDynamicApiController
{
[Route("Add")]
public void Add()
{
}
[Route("Edit")]
public void Edit()
{
}
}
[Route("api/system/SystemDictionary")]
public class SystemService : WithClass
{
public void Some()
{
}
}
动态WebAPI
实际上就是将普通的类变为 Controller
,也就是 动态WebAPI
就是控制器,支持控制器一切功能。