ASP.NET API通过NSwag生成客户端时String反序列化失败求助
解决NSwag客户端无法正确处理String返回类型的问题
问题原因
ASP.NET默认返回string类型时,会将其包装为JSON格式(比如返回"hello world"而非纯文本hello world),同时Swagger文档可能未正确标记该接口的返回类型为纯文本/字符串,导致NSwag生成的客户端错误地使用JSON反序列化逻辑处理响应,最终抛出反序列化失败的错误。
可行解决方案
方案1:修改API接口,明确返回内容类型
在API方法上添加[Produces("text/plain")]特性,并改用IActionResult返回内容,确保ASP.NET输出纯文本格式,同时让Swagger正确识别返回类型:
[HttpGet] [AllowAnonymous] [Produces("text/plain")] public IActionResult GetString() { return Content("hello world", "text/plain"); }
修改后重新生成Swagger文档,再用NSwag生成客户端即可正常处理字符串返回值。
方案2:修改NSwag生成命令,启用纯文本方法生成
在NSwag命令中添加/generatePlainTextMethods:true参数,让生成器专门处理返回纯文本的接口:
nswag openapi2csclient /input:http://localhost:5213/swagger/v1/swagger.json /output:Client.cs /namespace:MyApi.Client /generatePlainTextMethods:true
这个参数会让NSwag为返回纯文本的接口生成直接读取响应字符串的逻辑,跳过JSON反序列化步骤。
方案3:手动修改生成的客户端代码(临时方案)
如果暂时无法修改API或生成命令,可以手动调整生成的GetStringAsync方法,替换反序列化逻辑为直接读取响应内容:
public async System.Threading.Tasks.Task<string> GetStringAsync() { var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/[你的接口路径]"); var client_ = _httpClient; var disposeClient_ = false; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) { request_.Method = new System.Net.Http.HttpMethod("GET"); request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("text/plain")); PrepareRequest(client_, request_, urlBuilder_); var url_ = urlBuilder_.ToString(); request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); PrepareRequest(client_, request_, url_); var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseContentRead, System.Threading.CancellationToken.None).ConfigureAwait(false); try { var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); if (response_.Content != null && response_.Content.Headers != null) { foreach (var item_ in response_.Content.Headers) headers_[item_.Key] = item_.Value; } ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; if (status_ == 200) { // 替换原反序列化逻辑为直接读取字符串 var responseString_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); return responseString_; } else { var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); throw new ApiException(status_, "Response status code does not indicate success: " + status_, responseData_, headers_); } } finally { if (response_ != null) response_.Dispose(); } } } finally { if (disposeClient_) client_.Dispose(); } }
注意:此方法每次重新生成客户端都需要重复修改,适合临时应急使用。
内容的提问来源于stack exchange,提问作者Shkerbs
相关产品推荐
相关产品推荐

