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

使用WebClient调用接口时控制器string参数为空的问题排查

问题原因分析

这个问题我之前也碰到过,本质是ASP.NET Web API默认的JSON媒体格式化器对[FromBody]修饰的string类型参数有特殊的解析规则:

  • 当你传入纯数字内容(比如"123")时,格式化器会把它当作JSON数字类型,自动隐式转换为string,所以参数能正常接收;
  • 但当你传入带字母的内容(比如"A123")时,没有外层双引号的话,它不是合法的JSON字符串(JSON规范里字符串必须用双引号包裹),格式化器无法解析,就会导致参数为空,触发ModelState.IsValid失败。
解决办法

下面给你几个可行的方案,按推荐程度排序:

方案1:将上传的字符串序列化为标准JSON格式

在调用UploadString之前,把你的字符串参数序列化为符合JSON规范的字符串(也就是给它加上外层双引号)。可以用Newtonsoft.Json(大部分.NET项目都自带)来做:

using Newtonsoft.Json;
// ...
using (WebClient client = new WebClient()) { 
    client.BaseAddress = "http://localhost/"; 
    client.Headers.Add("Content-Type", "application/json"); 
    // 序列化为标准JSON字符串
    string jsonParameter = JsonConvert.SerializeObject(stringParameter);
    client.UploadString("api/test", HttpMethod.Put.ToString(), jsonParameter); 
}

这样不管你的参数是纯数字还是带字母的内容,都会被格式化为合法的JSON字符串,Web API能正确解析。

方案2:用DTO类包装参数

创建一个简单的数据传输对象(DTO)来包装你的字符串参数,这样Web API会按照JSON对象的规则解析,避免单个string参数的解析问题:

第一步:定义DTO类

public class TestRequest
{
    public string StringParameter { get; set; }
}

第二步:修改控制器方法

[Route("api/test")] 
[HttpPut] 
public async Task<IHttpActionResult> Test([FromBody] TestRequest request) { 
    if (!ModelState.IsValid || string.IsNullOrEmpty(request.StringParameter)) { 
        return BadRequest(ModelState); 
    } 
    // 使用request.StringParameter进行后续处理
    // ... 
}

第三步:修改WebClient调用代码

using Newtonsoft.Json;
// ...
using (WebClient client = new WebClient()) { 
    client.BaseAddress = "http://localhost/"; 
    client.Headers.Add("Content-Type", "application/json"); 
    var requestObj = new { StringParameter = stringParameter };
    string jsonParameter = JsonConvert.SerializeObject(requestObj);
    client.UploadString("api/test", HttpMethod.Put.ToString(), jsonParameter); 
}

这种方案更符合REST API的设计规范,后续如果需要增加参数也更方便扩展。

方案3:修改Web API的格式化器配置(不推荐)

如果你不想修改调用代码和控制器,可以配置Web API的JsonMediaTypeFormatter,让它支持解析不带引号的字符串,但这种方式不符合JSON规范,可能会带来其他潜在问题,所以只作为备选:
在WebApiConfig.cs的Register方法中添加:

config.Formatters.JsonFormatter.SerializerSettings.StringEscapeHandling = StringEscapeHandling.EscapeNonAscii;
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new StringConverter());

其中StringConverter是自定义的转换器:

public class StringConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.String)
        {
            return reader.Value.ToString();
        }
        // 如果是其他类型(比如数字、布尔),转成string
        return reader.Value?.ToString();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue(value.ToString());
    }
}

内容的提问来源于stack exchange,提问作者S. Cheng

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:11:48