如何在C# Web API客户端中无[FromBody]向.NET Core API传复杂对象
解决方案:无[FromBody]时C#客户端向.NET Core API发送复杂对象
我之前也碰到过一模一样的问题!核心原因是:ASP.NET Core在没有标记[FromBody]的情况下,会默认从表单编码数据(application/x-www-form-urlencoded)或者路由/查询参数里绑定复杂对象;而jQuery的$.post刚好默认就是用这种格式发送数据,所以能自动匹配,但C#客户端如果直接发JSON就会绑定失败。
下面给你具体的实现步骤:
1. 先确认你的控制器方法(补全你给出的代码)
首先确保你的控制器方法是接收FilterModel作为参数,没有[FromBody]:
[Serializable] public class FilterModel { public int? PageSize { get; set; } public int Page { get; set; } } [ApiController] [Route("api/[controller]")] public class TestController : ControllerBase { [HttpPost("TEST")] public virtual int Test(FilterModel filter) { // 示例逻辑:返回页码×每页数量(如果PageSize有值) return filter.PageSize.HasValue ? filter.Page * filter.PageSize.Value : filter.Page; } }
2. C#客户端用HttpClient发送表单编码数据
你需要把FilterModel转换成键值对形式的表单内容,而不是JSON。这里用FormUrlEncodedContent来实现:
using System.Net.Http; using System.Collections.Generic; using System.Threading.Tasks; // 注意:HttpClient建议全局复用,不要每次请求都新建 private static readonly HttpClient _httpClient = new HttpClient { BaseAddress = new Uri("https://your-api-base-url/api/Test/") }; public async Task<int> SendFilterRequest() { // 构建你的FilterModel对象 var filter = new FilterModel { Page = 3, PageSize = 15 }; // 将对象转换为表单键值对(处理可空类型,避免空值问题) var formData = new Dictionary<string, string> { ["Page"] = filter.Page.ToString(), ["PageSize"] = filter.PageSize?.ToString() ?? string.Empty }; // 创建表单编码的请求内容 var requestContent = new FormUrlEncodedContent(formData); // 发送POST请求 var response = await _httpClient.PostAsync("TEST", requestContent); response.EnsureSuccessStatusCode(); // 确保请求没有出错 // 读取返回的整数结果 var resultStr = await response.Content.ReadAsStringAsync(); return int.Parse(resultStr); }
3. 更通用的对象转表单扩展方法
如果你的复杂对象字段很多,可以写一个扩展方法自动转换,避免手动写键值对:
using System.Reflection; using System.Net.Http; using System.Collections.Generic; public static class ObjectToFormExtensions { public static FormUrlEncodedContent ToFormUrlEncodedContent(this object obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); // 反射获取对象的所有非空属性,转换为键值对 var properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(prop => prop.GetValue(obj) != null) .ToDictionary( prop => prop.Name, prop => prop.GetValue(obj)?.ToString() ?? string.Empty ); return new FormUrlEncodedContent(properties); } }
使用的时候就非常简洁了:
var requestContent = filter.ToFormUrlEncodedContent();
为什么jQuery能轻松实现?
因为jQuery的$.post方法默认会把JS对象序列化为application/x-www-form-urlencoded格式的键值对,和ASP.NET Core默认的绑定规则完全匹配,所以不需要额外配置就能成功绑定到FilterModel。
内容的提问来源于stack exchange,提问作者Kiradien
相关产品推荐
相关产品推荐

