使用PostAsJsonAsync请求WireMock返回404问题排查
问题根因
两种请求写法存在两个核心差异,都会导致WireMock的精确匹配规则失效,返回404:
- Content-Type头不匹配:
PostAsJsonAsync内部使用JsonContent封装请求体,默认携带的Content-Type值为application/json; charset=utf-8,而WireMock配置中使用WithHeader做精确字符串匹配,仅接受值为application/json的请求头,多出来的字符集参数直接导致头校验失败。 - 请求体内容不匹配:手动调用
JsonSerializer.Serialize时使用的是通用默认序列化配置,属性名保持C#类的帕斯卡命名格式,生成的请求体为{"ResponseType":"code"},和WireMock中配置的匹配字符串完全一致;但PostAsJsonAsync属于Web场景扩展方法,默认使用JsonSerializerDefaults.Web序列化配置,会自动将属性名转为小驼峰格式,实际发出的请求体为{"responseType":"code"},无法命中精确字符串匹配规则。
解决方案
可根据实际场景选择以下任意一种方案:
方案1:优化WireMock匹配规则(推荐)
替换脆弱的精确字符串匹配逻辑,使用WireMock内置的专用匹配器,适配常见的请求格式差异:
_authServer // 替换WithHeader的精确匹配,使用专用ContentType匹配器,自动忽略charset等附加参数 .Given(Request.Create() .WithPath("/v1/reauthuri") .WithContentType("application/json") .UsingPost() // 替换硬编码的序列化字符串,使用JSON匹配器,支持忽略属性名大小写 .WithBody(new JsonMatcher(new { ResponseType = "code" }, new JsonMatcherOptions { IgnoreCase = true // 自动适配帕斯卡/驼峰等命名差异 })) ) .RespondWith(Response.Create().WithStatusCode(HttpStatusCode.OK));
调整后不需要修改客户端调用代码,无论使用PostAsJsonAsync还是手动构造请求,只要语义符合要求就能正常匹配,规则鲁棒性更强。
方案2:统一客户端序列化与请求头配置
如果不希望调整WireMock规则,可以修改客户端调用逻辑,让PostAsJsonAsync的行为和手动序列化逻辑完全对齐:
// 配置序列化选项,关闭默认的驼峰命名转换,和手动序列化配置保持一致 var jsonOptions = new JsonSerializerOptions { PropertyNamingPolicy = null }; // 注意:此方案仍需调整WireMock的Content-Type匹配逻辑,接受带charset的头值 var response = await _httpClient.PostAsJsonAsync("/v1/reauthuri", authRequest, jsonOptions);
如果希望完全不修改WireMock原有配置,可继续使用手动序列化方式,显式构造不带charset参数的Content-Type头:
var str = System.Text.Json.JsonSerializer.Serialize(reAuthRequest); var content = new StringContent(str, Encoding.UTF8); // 显式设置Content-Type,不追加charset参数 content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); var response = await _httpClient.PostAsync("/v1/reauthuri", content);
内容的提问来源于stack exchange,提问作者Dr Schizo
相关产品推荐
相关产品推荐

