如何使WebMethods序列化ExpandoObject

5
我有一个 WebMethod,用于填充 jqGrid 的数据。
[System.Web.Script.Services.ScriptService]
public class MyWebService: System.Web.Services.WebService
{
    [WebMethod]
    [Authorize(Roles = "Admin")]
    public object GetPeople(bool _search, double nd, int rows, int page, string sidx, string sord)
    {
        var tbl = new DynamicModel("ConnStr", tableName: "Person", primaryKeyField: "ID");
        var results = tbl.Paged(orderBy: sidx + " " + sord, currentPage: page, pageSize: rows);
        return results;
    }

}

“results”是一个System.Dynamic.ExpandoObject对象,其中具有Items、TotalPages和TotalRecords属性。
我从webservice获取的json如下所示:
{
"d": [{
    "Key": "TotalRecords",
    "Value": 1
}, {
    "Key": "TotalPages",
    "Value": 1
}, {
    "Key": "Items",
    "Value": [
        [{
            "Key": "Row",
            "Value": 1
        }, {
            "Key": "ID",
            "Value": 1
        }, {
            "Key": "Name",
            "Value": "Test Template"
        }]
    ]
}]
}
} // Don't know why firebug put this extra bracket

理想情况下,我希望它返回时不会带有所有的键和值,因为这会使json膨胀并且与jqGrid不兼容。是否有一种方法可以改变ASP.NET处理ExpandoObject序列化的方式?

一位朋友推荐了这种方法https://dev59.com/Nm435IYBdhLWcg3w4UWs,但我不知道如何将JavaScriptConverter注册到WebMethod使用的JavaScriptSerializer中。 - Sean Tomlins
该死,我要找的答案在这里http://msdn.microsoft.com/en-us/library/bb763183.aspx大约在一半的位置。 - Sean Tomlins
很高兴知道你学到了新东西 :) - Jull
1个回答

4

听起来你已经明白了,但是这里有我之前写的代码片段,可以满足你的需求:

public class ExpandoObjectConverter : JavaScriptConverter {
  public override IEnumerable<Type> SupportedTypes {
    get { return new ReadOnlyCollection<Type>(new List<Type>(new Type[] { typeof(ExpandoObject) })); }
  }

  public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) {
    ExpandoObject expando = (ExpandoObject)obj;

    if (expando != null) {
      // Create the representation.
      Dictionary<string, object> result = new Dictionary<string, object>();

      foreach (KeyValuePair<string, object> item in expando) {
        if (item.Value.GetType() == typeof(DateTime))
          result.Add(item.Key, ((DateTime)item.Value).ToShortDateString());
        else
          result.Add(item.Key, item.Value.ToString());
      }

      return result;
    }
    return new Dictionary<string, object>();
  }

  public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) {
    return null;
  }
}

接下来,您只需要按照您链接的MSDN文章所示,将其添加到web.config中的<converters>部分即可:

<configuration>
  <system.web.extensions>
    <scripting>
      <webServices>
        <jsonSerialization>
          <converters>
            <add name="ExpandoObjectConverter" type="ExpandoObjectConverter"/>
          </converters>
        </jsonSerialization>
      </webServices>
    </scripting>
  </system.web.extensions>
</configuration>

是的,希望这能帮助其他人。尽管<jsonSerialization />应该是<jsonSerialization>,MSDN真可耻。谢谢你快速的回复Dave,喜欢你的工作,喜欢tekpub视频。 - Sean Tomlins
@SeanTomlins:啊,这就是我盲目信任MSDN的后果!感谢您指出这一点。我编辑了我的答案并联系了微软的某个人,希望能够修复这个错误。 - Dave Ward
除了值为null时,它的工作非常好。添加了一个检查,现在运行良好。foreach (KeyValuePair item in expando) { if (item.Value == null) result.Add(item.Key, string.Empty); else if (item.Value.GetType() == typeof(DateTime)) result.Add(item.Key, ((DateTime)item.Value).ToShortDateString()); else result.Add(item.Key, item.Value.ToString()); } - sarme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接