如何在启动时验证ASP.NET Core Minimal APIs的有效性?
在ASP.NET Core Minimal APIs(.NET 8)启动时检测端点绑定无效问题
我正在使用.NET 8的ASP.NET Core Minimal APIs开发应用,添加了若干端点。其中一个端点存在绑定无效问题,但应用仍能正常启动:
info: Microsoft.Hosting.Lifetime[14] Now listening on: http://localhost:5031 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down.
相关代码如下:
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/fine/{x}", (int x) => "I am {x}"); // 无效,因为无法将y绑定到NotBindable类型 app.MapGet("/bad/{y}", (NotBindable y) => $"I am {y.Value}"); app.Run(); public class NotBindable { public string Value { get; set; } }
当请求任一端点(无论有效与否)时,都会触发预期的异常:
System.InvalidOperationException: Body was inferred but the method does not allow inferred body parameters. Below is the list of parameters that we found: Parameter | Source --------------------------------------------------------------------------------- y | Body (Inferred) Did you mean to register the "Body (Inferred)" parameter(s) as a Service or apply the [FromServices] or [FromBody] attribute?
希望在应用启动时就检测到该错误,而非首次访问端点时才出现,如何实现?
解决方案
可以通过在启动阶段主动验证所有端点的绑定规则来实现,核心思路是提前解析端点元数据,检查参数绑定的合法性,一旦发现无效绑定就抛出异常终止启动。
实现代码
在app.Run()之前添加以下验证逻辑:
// 获取所有已注册的端点数据源 var endpointDataSource = app.Services.GetRequiredService<EndpointDataSource>(); var routeEndpoints = endpointDataSource.Endpoints.OfType<RouteEndpoint>(); foreach (var endpoint in routeEndpoints) { // 获取请求委托的参数绑定信息 var requestDelegateInfo = endpoint.Metadata.GetMetadata<RequestDelegateMetadata>()?.RequestDelegateInfo; if (requestDelegateInfo == null) continue; foreach (var param in requestDelegateInfo.Parameters) { var bindingSource = param.BindingInfo?.BindingSource; // 针对GET请求:不允许使用Body绑定(包括推断的Body绑定) if (endpoint.RoutePattern.HttpMethod?.Contains("GET") == true && bindingSource == BindingSource.Body) { throw new InvalidOperationException( $"启动验证失败:端点 {endpoint.RoutePattern.RawText} 的参数「{param.Name}」使用了Body绑定,GET请求不支持该绑定方式。"); } // 可扩展其他验证场景:比如自定义类型缺少绑定转换器等 if (param.ParameterType == typeof(NotBindable) && bindingSource != BindingSource.Path && bindingSource != BindingSource.Query) { throw new InvalidOperationException( $"启动验证失败:端点 {endpoint.RoutePattern.RawText} 的参数「{param.Name}」无法绑定,请为NotBindable类型添加绑定转换器或指定正确的绑定源。"); } } }
说明
- 这段代码会遍历所有路由端点,检查每个参数的绑定源是否符合HTTP方法的规则(比如GET请求禁止Body绑定)
- 可以根据实际需求扩展验证逻辑,比如检查自定义类型是否有对应的绑定转换器
- 验证逻辑放在
app.Run()之前,一旦检测到无效绑定,应用会直接抛出异常并终止启动,不会进入监听状态
内容的提问来源于stack exchange,提问作者mMilk
相关产品推荐
相关产品推荐

