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

解决WebMethod返回JSON被{d:}包裹致UWP反序列化失败问题

解决ASMX WebMethod返回JSON被d字段包裹的问题

这个问题我太熟悉了!你遇到的{"d":"..."}是ASMX WebMethod的默认行为——ASP.NET为了防止JSON劫持,会自动把返回值包装在d字段里。而你的代码里还额外手动序列化了一次对象成字符串,导致了双重序列化:WebMethod把你返回的JSON字符串当成普通字符串值,又给它套了一层d包装,最终返回的是转义后的字符串,自然反序列化不了TestClass。

下面给你几种靠谱的解决思路:

1. 最规范的做法:直接返回对象,让ASP.NET自动序列化

别手动调用JsonConvert.SerializeObject了!WebMethod支持直接返回强类型对象,ASP.NET会帮你完成序列化,而且返回的d字段里是正确的对象JSON(不是字符串)。

修改你的WebMethod:

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public TestClass PostDropDowns() {
    TestClass t = new TestClass() { 
        abc = "this has been sent over", 
        Strings = new List<string> { "fdfdfd", "fdfdfdf" } 
    };
    // 直接返回对象,不用手动序列化
    return t;
}

然后客户端收到的响应是:

{"d":{"abc":"this has been sent over","Strings":["fdfdfd","fdfdfdf"]}}

这时候客户端可以通过两种方式反序列化:

方式A:用包装类接收

创建一个通用的包装类,专门处理ASMX的d字段:

public class JsonResponseWrapper<T> {
    public T d { get; set; }
}

然后反序列化:

var wrapper = JsonConvert.DeserializeObject<JsonResponseWrapper<TestClass>>(responseFromServer);
var dds = wrapper.d; // 这就是你要的TestClass实例

方式B:直接解析JObject取出d的值

如果不想创建包装类,可以用Newtonsoft.Json的JObject直接提取:

var responseObj = JObject.Parse(responseFromServer);
var testClassJson = responseObj["d"].ToString();
var dds = JsonConvert.DeserializeObject<TestClass>(testClassJson);

2. 直接返回纯净JSON(你已经用的方法)

如果一定要绕过d字段,直接返回纯净的JSON,你手动写入响应流的方法是可行的。不过可以稍微优化一下代码,让它更简洁:

[WebMethod]
public void PostDropDowns() {
    TestClass t = new TestClass() { 
        abc = "this has been sent over", 
        Strings = new List<string> { "fdfdfd", "fdfdfdf" } 
    };
    var json = JsonConvert.SerializeObject(t);
    
    var response = HttpContext.Current.Response;
    response.Clear();
    response.ContentType = "application/json; charset=utf-8";
    response.Write(json);
    response.End();
}

这种方法完全绕过了WebMethod的默认包装逻辑,直接输出JSON字符串,客户端收到的就是你预期的纯净JSON,不需要额外处理。

为什么会有d字段?

最后说下背景:ASP.NET添加d字段是为了防止JSON劫持攻击。如果直接返回数组(比如["a","b","c"]),攻击者可以通过<script>标签加载你的接口,然后劫持数组数据。而把返回值包装在对象里({"d": [...]}),脚本无法直接获取到数组,就避免了这个风险。所以如果没有特殊需求,更推荐用第一种规范的方法,兼顾安全和代码简洁。

内容的提问来源于stack exchange,提问作者iandavidson1982

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:55:54