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

Xamarin跨平台应用Android端调用WebService返回DataTable触发序列化异常

问题原因及解决方案

核心原因

这个错误本质是Xamarin Android(基于Mono运行时)与Windows .NET Framework在WebService代理类反射、DataTable类型处理上的兼容性差异:

  • .NET Framework对DataTable的序列化/反序列化支持完善,但Mono对DataTable的反射机制支持有限,自动生成的WebService代理类在处理返回DataTable的方法时,反射GetSeccoesResponseGetSeccoesResult类型会失败。
  • 自动生成的代理类中,部分内部类型的访问权限在Android平台下无法被正常反射,而Windows环境对此限制更宽松。

具体解决方案

1. 替换WebService返回类型(最优解)

修改WebService的GetSeccoes方法,不再返回DataTable,改为返回自定义实体类列表(比如List<SeccaoCentro>):

  • 服务端定义与客户端一致的SeccaoCentro类,将数据库查询结果映射为实体列表后返回。
  • 重新生成客户端WebService代理,此时代理类会生成强类型返回对象,完全绕过DataTable的跨平台兼容性问题。

2. 绕过自动代理类,手动调用WebService

如果无法修改服务端,直接跳过自动生成的wsProducao代理,用Http请求手动调用并解析XML:

async void CarregaSeccoes()
{
    List<SeccaoCentro> Seccoes = new List<SeccaoCentro>();
    var soapRequest = @"<?xml version=""1.0"" encoding=""utf-8""?>
                        <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
                          <soap:Body>
                            <GetSeccoes xmlns=""你的WebService命名空间"">
                              <TipoPlataforma>" + Application.Current.Properties["TipoPlataforma"] + @"</TipoPlataforma>
                              <Empresa>" + Application.Current.Properties["Empresa"] + @"</Empresa>
                              <Utilizador>" + Application.Current.Properties["Utilizador"] + @"</Utilizador>
                              <Password>" + Application.Current.Properties["Password"] + @"</Password>
                            </GetSeccoes>
                          </soap:Body>
                        </soap:Envelope>";

    var request = (HttpWebRequest)WebRequest.Create("你的WebService地址");
    request.Method = "POST";
    request.ContentType = "text/xml; charset=utf-8";
    request.Headers.Add("SOAPAction", "你的WebService命名空间/GetSeccoes");

    using (var streamWriter = new StreamWriter(request.GetRequestStream()))
    {
        streamWriter.Write(soapRequest);
    }

    using (var response = (HttpWebResponse)await request.GetResponseAsync())
    using (var streamReader = new StreamReader(response.GetResponseStream()))
    {
        var xmlResponse = streamReader.ReadToEnd();
        XmlDocument xml = new XmlDocument();
        xml.LoadXml(xmlResponse);

        // 注意调整XPath,匹配实际返回的XML结构
        XmlNodeList xNodeList = xml.SelectNodes("//GetSeccoesResult/DocumentElement/Seccoes");
        foreach (XmlNode xNode in xNodeList)
        {
            Seccoes.Add(new SeccaoCentro()
            {
                IDSeccao = Convert.ToInt32(xNode["IDSeccao"].InnerText),
                Seccao = xNode["Seccao"].InnerText,
                Descricao = xNode["Seccao"].InnerText.ToUpper() + " - " + xNode["Descricao"].InnerText.ToUpper()
            });
        }
    }

    cvSeccoes.ItemsSource = Seccoes.Count > 0 ? Seccoes : null;
}

3. 调整代理类的访问权限(临时方案)

如果坚持使用自动生成的代理类:

  • 找到生成的Producao.cs代理文件,检查GetSeccoesResponseGetSeccoesResult类型的访问修饰符,确保它是public的。
  • 若该类型为internal,修改为public——Android平台的反射机制对非public类型的访问限制更严格。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 13:46:04