如何为ASP.NET Core 5.0 Web API特定Action禁用自动模型绑定
解决ASP.NET Core 5.0 Web API中特定Action禁用自动模型绑定的问题
首先咱们拆解下你遇到的问题:当Action包含[FromRoute]参数时,ASP.NET Core的[ApiController]特性会自动根据请求的Content-Type尝试解析请求体——哪怕你根本没声明需要从请求体绑定任何参数。第三方发来的application/x-www-form-urlencoded类型请求体实际是二进制数据,框架尝试把它解析成表单键值对时自然会抛出ArgumentException;而移除路由参数后,框架可能认为没有需要绑定的内容,就跳过了解析步骤,所以报错消失。
要解决这个问题,我们可以针对这个特定Action禁用表单值的自动模型绑定,既保留路由参数的正常获取,又能自行读取原始二进制请求体。具体步骤如下:
步骤1:创建自定义禁用表单绑定的特性
我们需要实现一个资源过滤器,在模型绑定之前移除表单值的提供器,这样框架就不会尝试解析请求体的表单数据了:
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.ModelBinding; using System; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter { public void OnResourceExecuting(ResourceExecutingContext context) { // 移除表单值和JQuery表单值的提供器,阻止框架解析表单请求体 var valueProviderFactories = context.ValueProviderFactories; valueProviderFactories.RemoveType<FormValueProviderFactory>(); valueProviderFactories.RemoveType<JQueryFormValueProviderFactory>(); } public void OnResourceExecuted(ResourceExecutedContext context) { // 执行后无需额外操作 } }
步骤2:将特性应用到目标Action
把这个自定义特性添加到你的Validation_Post方法上,这样该Action就会跳过表单值的自动绑定:
[Route("~/Validation")] [ApiController] public class ValidationController : ControllerBase { [HttpPost("{requestId}")] [Consumes(@"application/octet-stream", @"application/x-www-form-urlencoded")] [Produces(@"application/octet-stream")] [DisableFormValueModelBinding] // 新增这个特性 public async Task<IActionResult> Validation_Post([FromRoute] string requestId) { byte[] rawRequestBody = Array.Empty<byte>(); // 优化请求体读取逻辑(可选,原代码也可正常工作) Request.EnableBuffering(); // 启用缓冲,确保流可Seek using (var ms = new MemoryStream()) { await Request.Body.CopyToAsync(ms); rawRequestBody = ms.ToArray() ?? throw new NullReferenceException(); Request.Body.Seek(0, SeekOrigin.Begin); // 重置流位置,避免后续中间件读取异常 } // TODO: Handle rawRequestBody data. return new FileContentResult(new byte[] { 1 }, @"application/octet-stream") { EnableRangeProcessing = true, LastModified = DateTime.UtcNow }; } }
方案生效原因
- 路由参数
requestId是从URL路径绑定的,不受表单值绑定禁用的影响,依然可以正常获取。 - 移除
FormValueProviderFactory和JQueryFormValueProviderFactory后,框架不会再尝试解析application/x-www-form-urlencoded类型的请求体为表单键值对,彻底避免了解析二进制数据时的异常。 - 你依然可以正常读取原始二进制请求体,处理第三方发来的数据。
内容的提问来源于stack exchange,提问作者burnersk
相关产品推荐
相关产品推荐

