You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 03:32:47