2015-05-26 57 views
1

我有一個簡單的Web服務創建用於學習的目的,它只有兩個方法實現,一個將對象添加到列表中,另一個返回列表。問題在於該服務不包含對象的序列化列表。返回值是一個空數組。 我在同一解決方案中創建了一個簡單的控制檯應用程序,並使用VS 2013中的內置嚮導爲其添加了服務引用。這些是生成的文件:http://i.imgur.com/ql0QUZN.png這三個.xsd文件很奇怪,爲什麼不只是一個?Web服務不返回序列化列表

解決方案本身被設置爲多個啓動項目(包括服務和客戶端應用程序),「無需調試即可啓動」模式 - 如果這很重要。

這裏是WCF測試客戶端輸出:

NewStudent呼叫 - http://i.imgur.com/Q41lq4L.png

StudentList呼叫 - http://i.imgur.com/ULQULdW.png

如果需要的話,我會提供更多的信息,預先感謝您。

Web服務代碼:

IService.cs

namespace CollegeService 
{ 
    [ServiceContract] 
    public interface IService 
    { 
     [OperationContract] 
     List<Student> StudentList(); 

     [OperationContract] 
     void NewStudent(Student s); 
    } 

    [DataContract] 
    public class Student 
    { 
     private string _OIB; // unique identifier 
     private string _name; 
     private string _schoolYear; 

     [DataMember] 
     public string OIB 
     { 
      get { return _OIB; } 
      set { _OIB = value; } 
     } 

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

     [DataMember] 
     public string SchoolYear 
     { 
      get { return _schoolYear; } 
      set { _schoolYear = value; } 
     } 
    } 
} 

Service.svc

<%@ ServiceHost Language="C#" Debug="true" Service="CollegeService.Service" CodeBehind="Service.svc.cs" %> 

Service.svc.cs

namespace CollegeService 
{ 
    public class Service : IService 
    { 
     private List<Student> _students; 

     public Service() 
     { 
      this._students = new List<Student>(); 
     } 

     public void NewStudent(Student s) 
     { 
      this._students.Add(s); 
     } 

     public List<Student> StudentList() 
     { 
      return this._students; 
     } 
    } 
} 

客戶端代碼:

Reference.cs

//------------------------------------------------------------------------------ 
// <auto-generated> 
//  This code was generated by a tool. 
//  Runtime Version:4.0.30319.34209 
// 
//  Changes to this file may cause incorrect behavior and will be lost if 
//  the code is regenerated. 
// </auto-generated> 
//------------------------------------------------------------------------------ 

namespace CollegeServiceClient.Service { 
    using System.Runtime.Serialization; 
    using System; 


    [System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")] 
    [System.Runtime.Serialization.DataContractAttribute(Name="Student", Namespace="http://schemas.datacontract.org/2004/07/CollegeService")] 
    [System.SerializableAttribute()] 
    public partial class Student : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged { 

     [System.NonSerializedAttribute()] 
     private System.Runtime.Serialization.ExtensionDataObject extensionDataField; 

     [System.Runtime.Serialization.OptionalFieldAttribute()] 
     private string NameField; 

     [System.Runtime.Serialization.OptionalFieldAttribute()] 
     private string OIBField; 

     [System.Runtime.Serialization.OptionalFieldAttribute()] 
     private string SchoolYearField; 

     [global::System.ComponentModel.BrowsableAttribute(false)] 
     public System.Runtime.Serialization.ExtensionDataObject ExtensionData { 
      get { 
       return this.extensionDataField; 
      } 
      set { 
       this.extensionDataField = value; 
      } 
     } 

     [System.Runtime.Serialization.DataMemberAttribute()] 
     public string Name { 
      get { 
       return this.NameField; 
      } 
      set { 
       if ((object.ReferenceEquals(this.NameField, value) != true)) { 
        this.NameField = value; 
        this.RaisePropertyChanged("Name"); 
       } 
      } 
     } 

     [System.Runtime.Serialization.DataMemberAttribute()] 
     public string OIB { 
      get { 
       return this.OIBField; 
      } 
      set { 
       if ((object.ReferenceEquals(this.OIBField, value) != true)) { 
        this.OIBField = value; 
        this.RaisePropertyChanged("OIB"); 
       } 
      } 
     } 

     [System.Runtime.Serialization.DataMemberAttribute()] 
     public string SchoolYear { 
      get { 
       return this.SchoolYearField; 
      } 
      set { 
       if ((object.ReferenceEquals(this.SchoolYearField, value) != true)) { 
        this.SchoolYearField = value; 
        this.RaisePropertyChanged("SchoolYear"); 
       } 
      } 
     } 

     public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; 

     protected void RaisePropertyChanged(string propertyName) { 
      System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; 
      if ((propertyChanged != null)) { 
       propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] 
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName="Service.IService")] 
    public interface IService { 

     [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/StudentList", ReplyAction="http://tempuri.org/IService/StudentListResponse")] 
     CollegeServiceClient.Service.Student[] StudentList(); 

     [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/StudentList", ReplyAction="http://tempuri.org/IService/StudentListResponse")] 
     System.Threading.Tasks.Task<CollegeServiceClient.Service.Student[]> StudentListAsync(); 

     [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/NewStudent", ReplyAction="http://tempuri.org/IService/NewStudentResponse")] 
     void NewStudent(CollegeServiceClient.Service.Student s); 

     [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/NewStudent", ReplyAction="http://tempuri.org/IService/NewStudentResponse")] 
     System.Threading.Tasks.Task NewStudentAsync(CollegeServiceClient.Service.Student s); 
    } 

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] 
    public interface IServiceChannel : CollegeServiceClient.Service.IService, System.ServiceModel.IClientChannel { 
    } 

    [System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] 
    public partial class ServiceClient : System.ServiceModel.ClientBase<CollegeServiceClient.Service.IService>, CollegeServiceClient.Service.IService { 

     public ServiceClient() { 
     } 

     public ServiceClient(string endpointConfigurationName) : 
       base(endpointConfigurationName) { 
     } 

     public ServiceClient(string endpointConfigurationName, string remoteAddress) : 
       base(endpointConfigurationName, remoteAddress) { 
     } 

     public ServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
       base(endpointConfigurationName, remoteAddress) { 
     } 

     public ServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
       base(binding, remoteAddress) { 
     } 

     public CollegeServiceClient.Service.Student[] StudentList() { 
      return base.Channel.StudentList(); 
     } 

     public System.Threading.Tasks.Task<CollegeServiceClient.Service.Student[]> StudentListAsync() { 
      return base.Channel.StudentListAsync(); 
     } 

     public void NewStudent(CollegeServiceClient.Service.Student s) { 
      base.Channel.NewStudent(s); 
     } 

     public System.Threading.Tasks.Task NewStudentAsync(CollegeServiceClient.Service.Student s) { 
      return base.Channel.NewStudentAsync(s); 
     } 
    } 
} 

Program.cs中(入口點)

namespace CollegeServiceClient 
{ 
    public class Program 
    { 
     static void Main(string[] args) 
     { 
      ServiceClient client = new ServiceClient(); 
      try 
      { 
       client.Open(); 
       client.NewStudent 
        (new Student 
         { 
          OIB = "1234", 
          Name = "John Doe", 
          SchoolYear = "4" 
         } 
        ); 
       Student[] students = client.StudentList(); 
       foreach (Student s in students) 
       { 
        Console.WriteLine("Student OIB: {0} Name: {1} School year: {2}", s.OIB, s.Name, s.SchoolYear); 
       } 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.Message); 
      } 
      finally 
      { 
       client.Close(); 
      } 
     } 
    } 
} 
+0

加上'[DataContract]'在Student'的'頂部。另外認爲你的'[DataMember]'屬性應該覆蓋變量本身,而不是它們的訪問器方法。 – npinti

+0

它已經存在了,我只是在將代碼粘貼到此處時誤刪了它。 – Venom

+0

然後請更新你的反映你有什麼。另外,我認爲您需要將「DataMember」屬性移到變量上,而不是通過它們的訪問器。 – npinti

回答

1

原來,問題是作爲一個說明here相同。在你的情況下,類的實例被實例化爲,每個調用,因此,你的列表總是被重置。

要解決此問題,只需將[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]屬性添加到Service類。這應該確保使用相同的類實例來處理您的呼叫。

這是我的代碼的外觀:

namespace CollegeService 
{ 
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together. 
    [ServiceContract] 
    public interface IService 
    { 
     [OperationContract] 
     List<Student> StudentList(); 

     [OperationContract] 
     void NewStudent(Student s); 
    } 

    // Use a data contract as illustrated in the sample below to add composite types to service operations. 
    // You can add XSD files into the project. After building the project, you can directly use the data types defined there, with the namespace "CollegeService.ContractType". 
    [DataContract] 
    public class Student 
    { 

     [DataMember] 
     public string OIB 
     { 
      get; 
      set; 
     } 

     [DataMember] 
     public string Name 
     { 
      get; 
      set; 
     } 

     [DataMember] 
     public string SchoolYear 
     { 
      get; 
      set; 
     } 
    } 
} 

namespace CollegeService 
{ 
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together. 
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)] 
    public class Service : IService 
    { 
     private List<Student> _students; 

     public Service() 
     { 
      this._students = new List<Student>(); 
     } 

     public void NewStudent(Student s) 
     { 
      this._students.Add(s); 
     } 

     public List<Student> StudentList() 
     { 
      return this._students; 
     } 
    } 
} 
+0

現在有效,謝謝。但是,我使用的get和set語法怎麼樣?可以以某種方式工作嗎?我的工作也是(只是檢查它),而不添加DataMember數據成員,只是訪問者。 – Venom

+0

@Venom:是的,它確實有效。我改變它的唯一原因是因爲它寫的較短。 – npinti

+0

WCF測試客戶端現在也可以工作。 – Venom