【问题标题】:Deserialization of given data in Win8AppWin8App中给定数据的反序列化
【发布时间】:2016-01-17 19:58:34
【问题描述】:

我有一个 Win8App 和一个 WCF。 Win8App 进行不同的调用,WCF 提供ListObservableCollections 的自定义类,如以下示例中的Person。我的问题是每个列表或集合在到达我的 Win8App 时都是空的(不为空)。我发现这是关于反序列化的,但现在该怎么办?

我用ListArrayObservableCollectionIList 或只是一个对象编写了一些测试代码,但我从来没有遇到异常,但总是空的(非空)集合或空的单个对象。是我的 WCF/Win8App 的反序列化问题还是配置问题?

WCF IService.cs:

[ServiceContract]
public interface IMyService
{       
    [OperationContract(Name = "GetPerson")]
    Person GetPerson();

    [OperationContract(Name = "GetPersons")]
    List<Person> GetPersons();

    [OperationContract(Name = "GetPersonArray")]
    Person[] GetPersonArray();

    [OperationContract(Name = "GetPersonList")]
    IList<Person> GetPersonList();

    [OperationContract(Name = "GetPersonCollection")]
    ObservableCollection<Person> GetPersonCollection();        
}

WCF .svc:

public Person GetPerson()
{
    return new Person() { Name = "asdf", IstZeit = new TimeSpan(10000000) };
}

public List<Person> GetPersons()
{
    List<Person> list = new List<Person>();
    for (int i = 0; i < 19; i++)
    {
        list.Add(new Person() { Name = "asdf", IstZeit = new TimeSpan(10000000) });

    }
    return list;
}


public ObservableCollection<Person> GetPersonCollection()
{
    ObservableCollection<Person> list = new ObservableCollection<Person>();
    for (int i = 0; i < 19; i++)
    {
        list.Add(new Person() { Name = "asdf", IstZeit = new TimeSpan(10000000) });

    }
    return list;
}

public Person[] GetPersonArray()
{
   List<Person> list = new List<Person>();
   for (int i = 0; i < 19; i++)
   {
       list.Add(new Person() { Name = "asdf", IstZeit = new TimeSpan(10000000) });

   }
   return list.ToArray();
}

public IList<Person> GetPersonList()
{
    List<Person> list = new List<Person>();
    for (int i = 0; i < 19; i++)
    {
        list.Add(new Person() { Name = "asdf", IstZeit = new TimeSpan(10000000) });

    }
    return list;
}

WCF - 类人

[DataContract]
public class Person
{
    private string name;
    private string email;
    private TimeSpan istZeit;

    public Person()
    {

    }

    [DataMember]
    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    [DataMember]
    public TimeSpan IstZeit
    {
        get { return istZeit; }
        set { istZeit = value; }
    }

    [DataMember]
    public string Email
    {
        get { return email; }
        set { email = value; }
    }
}

现在我的 Win8App .....

通过 ChannelFactory 设置 ServiceReference:

public static IMyService GetClientForService()
{
    EndpointAddress endpointAddress = new EndpointAddress("http://localhost:12345/Service1.svc");

    BasicHttpBinding basicHttpBinding = new BasicHttpBinding();     

    ChannelFactory<IMyService> channelFactory = channelFactory = new ChannelFactory<IMyService>(basicHttpBinding, endpointAddress);
    IMyService client = channelFactory.CreateChannel();            

    return client;
}

在我的 Win8App 中,我为 IMyServicePerson 实现了与 WCF 中相同的代码。

此方法正在调用 WCF:

private void CheckWCFMethods()
{
    IMyService client = ServiceBinding.GetClientForService();

    var p = client.GetPerson();
    IList<Person> iList = client.GetPersonList();
    ObservableCollection<Person> collection = client.GetPersonCollection();
    Person[] array = client.GetPersonArray();
    List<Person> list = client.GetPersons();

    #if(DEBUG)
    Debug.WriteLine(string.Format("SinglePersonName:{0}\niList.Count:{1}\nCollection.Count:{2}\nArray.Length:{3}\nList.Count:{4}",string.IsNullOrEmpty(p.Name) ? "empty" : p.Name, iList.Count, collection.Count, array.Length, list.Count));
    Debug.WriteLine("DONE");
    #endif
}

调试结果总是:

**DEBUGRESULT**
SinglePersonName:empty
IList.Count:0
Collection.Count:0
Array.Length:0
List.Count:0
DONE

但是当我通过 WCF-Testclient 直接执行 WCF 时,我得到了:

SinglePersonName: asdf
IList.Count:19
Collection.Count:19
Array.Length:19
List.Count:19


我尝试设置[KnownType][ServiceKnownType](服务器端和客户端),但没有任何改变。我以前只写过 2 或 3 个 WCF,但从来不需要处理反序列化问题,因为当我通过 Visual Studio 设置 ServiceReference 时,会自动设置集合类型和字典集合类型(或通过简单的点击)。所以我是 ChannelFactory 的新手,也是服务器端和客户端的序列化编码的新手。

我应该怎么做才能反序列化 Win8App 中的数据?


如果您需要任何进一步的信息,请告诉我!


** 编辑 **

所以我尝试为客户端的人员类设置命名空间(class Person 在我的 TestWCF 中名为“DataContracts”的文件夹中):

[DataContract(Namespace = "http://localhost:12345/DataContracts")]
public class Person{}

但结果仍然是这样的:

**DEBUGRESULT**
SinglePersonName:empty
IList.Count:0
Collection.Count:0
Array.Length:0
List.Count:0
DONE

** 编辑 **

所以我用我的 Windows 8.1 测试应用程序尝试了一些东西,这让我感到困惑,正常的 Visual Studio 服务引用运行良好,而我的 channelfactory“引用”什么也没做 - 无法弄清楚它有什么问题:

我真的很困惑,如果你想自己尝试一下,你可以在这里下载这个示例 wcf 和 w8.1app(我的 googledrive): Testfiles

你只需要在win8.1应用程序中设置端点地址的uri并启动wcf(或在iis上发布)。

关于这个主题的任何进一步信息?

【问题讨论】:

  • 当您说“在我的 Win8App 中,我为 IMyService 和 Person 实现了与 WCF 中相同的代码”时,您是否将数据合同和服务合同定义从服务复制/粘贴到您的客户端应用程序?跨度>
  • @carlosfigueira - 是的,我创建了一个类,其中实现了接口和所有需要的类?不正确?就像谷歌告诉我的那样 - 我应该如何实现服务接口?

标签: c# .net wcf serialization deserialization


【解决方案1】:

如果您按原样复制/粘贴数据/服务合同,那么您可能会遇到 XML 命名空间不匹配的问题。当通过 WCF 请求/响应中的线路传输的 XML 时,其元素位于某些 XML 命名空间内。当您定义 [DataContract][ServiceContract] 而不明确指定要使用的 XML 命名空间时,WCF 将默认使用从类本身的命名空间(即其 CLR 命名空间)派生的命名空间。

如果您有两个类,一个在客户端,一个在服务器上用于数据协定,但它们位于不同的 CLR 命名空间(例如,MyApp.Service.PersonMyApp.Client.Person),那么使用的 XML通过 WCF 对应的那些类是不同的。

如果确实如此,请尝试在数据合约上明确定义命名空间,这样就不会再发生这种不匹配:

[DataContract(Namespace = "http://my.company.com/contracts")]
public class Person
{
    private string name;
    private string email;
    private TimeSpan istZeit;

    public Person()
    {

    }

    [DataMember]
    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    [DataMember]
    public TimeSpan IstZeit
    {
        get { return istZeit; }
        set { istZeit = value; }
    }

    [DataMember]
    public string Email
    {
        get { return email; }
        set { email = value; }
    }
}

另一种选择是在客户端项目的 Visual Studio 上使用诸如“添加服务引用”之类的工具,将其指向服务元数据(如果您启用了它)。该工具将使用适当的命名空间声明创建要在客户端中使用的类。

【讨论】:

  • 因为“添加服务参考” - 这是我的问题。我已经用BasicHTTPAuthentification 修改了 WCF,但无法添加引用,因为我必须验证大约 100 次才能引发错误。这就是为什么我想通过 ChannelFactory 添加“参考”。身份验证工作正常,但现在我遇到了自定义类和通用列表和集合的(反)序列化问题。我将尝试使用命名空间属性,但此属性对列表和集合有帮助吗?
  • 我的命名空间看起来像一个 URL 吗? [DataContract(Namespace = "http://localhost:port/Service1.svc")] 是否足够,还是我必须指定类在 wcf 中的哪个文件夹中?
  • 更新了我的问题 - 在客户端添加了命名空间到 class Person,但它并没有改变任何事情。我必须在任何地方设置[KnownType][ServiceKnownType] 吗?
  • 我查看了您从更新的问题中链接的 .zip 文件;服务器端Person 类中的[DataContract] 属性没有定义任何Namespace(因此它将采用默认值,例如"http://schemas.datacontract.org/2004/07/WcfService1.DataContracts"),而在客户端你有它。尝试在类的客户端和服务器版本上定义相同的命名空间,这应该会开始工作。
  • 谢谢!在两边设置命名空间解决了我的问题。现在我必须对原始 WCF 和 Win8App 编码进行分类/重新排序/调整。因此,如果我为每个自定义类设置名称空间,它应该可以工作。再次感谢您。
【解决方案2】:

您应该使用[ServiceContract] 属性标记接口

[ServiceContract]
public interface IMyService

【讨论】:

  • 对不起我的错 - 我已经设置了这个属性。忘记写在这里的示例代码中了!
【解决方案3】:

今天我遇到了一个问题,序列化程序在尝试反序列化时间跨度时窒息。在我的情况下,从要序列化的对象中删除时间跨度解决了这个问题。我能够用整数(秒数)替换时间跨度,不确定这是否适合您,但可能需要检查。

【讨论】:

  • 感谢您的回答,但没有帮助!我推荐 carlosfigueiras 的答案 - 在服务器端和客户端设置命名空间是解决方案。
猜你喜欢
  • 1970-01-01
  • 2014-11-18
  • 2020-02-11
  • 2021-10-27
  • 1970-01-01
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多