2012-02-27 83 views
1

我从ASP.NET网站调用WCF服务时出现以下异常。我们如何克服它?当返回接口对象列表时WCF异常

注意:通过在服务项目中应用中断点,我已验证该服务正在返回两个有效对象。

注意:在服务中,我正在返回IBankAccount清单。 [OperationContract] List<IBankAccount> GetDataUsingDataContract(int userId); IBankAccount是一个接口。

例外说“底层连接已关闭:连接意外关闭”。详细的堆栈跟踪在下图中可用。

enter image description here

//网站

using System; 
using ServiceReference1; 
public partial class _Default : System.Web.UI.Page 
{ 
protected void Page_Load(object sender, EventArgs e) 
{ 

    Service1Client client = new Service1Client(); 

    string result = client.GetData(1); 
    Response.Write(result); 


    client.GetDataUsingDataContract(1); 
    int d = 0; 

} 
} 

//服务接口

using System.Collections.Generic; 
using System.ServiceModel; 
using DTOProject; 
namespace MyServiceApp 
{ 
[ServiceContract] 
public interface IService1 
{ 
    [OperationContract] 
    string GetData(int value); 

    [OperationContract] 
    List<IBankAccount> GetDataUsingDataContract(int userId); 

} 

} 

// DTO

using System.Runtime.Serialization; 
namespace DTOProject 
{ 
public interface IBankAccount 
{ 
    int Duration { get; set; } 
    int AmountDeposited { get; set; } 
} 
} 

using System.Runtime.Serialization; 
namespace DTOProject 
{ 
[DataContract] 
public class FixedAccount : IBankAccount 
{ 
    [DataMember] 
    public int Duration { get; set; } 

    [DataMember] 
    public int AmountDeposited { get; set; } 
} 
} 

using System.Runtime.Serialization; 
namespace DTOProject 
{ 
[DataContract] 
public class SavingsAccount : IBankAccount 
{ 
    [DataMember] 
    public int Duration { get; set; } 

    [DataMember] 
    public int AmountDeposited { get; set; } 
} 
} 

//服务实现

using System.Collections.Generic; 
using DTOProject; 
using BusinessLayer; 

namespace MyServiceApp 
{ 
public class Service1 : IService1 
{ 
    public string GetData(int value) 
    { 
     return string.Format("You entered: {0}", value); 
    } 
    public List<IBankAccount> GetDataUsingDataContract(int userId) 
    { 
     BusinessLayer.AccountManager accManager = new AccountManager(); 
     List<IBankAccount> accounts = accManager.GetAllAccountsForUser(userId); 
     return accounts; 
    } 

} 
} 

//业务层

using System.Collections.Generic; 
using DTOProject; 
using DataAccessLayer; 
namespace BusinessLayer 
{ 
public class AccountManager 
{ 
    public List<IBankAccount> GetAllAccountsForUser(int userID) 
    { 
     DataAccessLayer.AccounutManagerDAL accountManager = new AccounutManagerDAL(); 
     List<IBankAccount> accountList = accountManager.GetAllAccountsForUser(userID); 
     return accountList; 
    } 

} 
} 

//数据访问层

using System; 
using System.Collections.Generic; 
using DTOProject; 
namespace DataAccessLayer 
{ 

public class DatabaseRecordSimulation 
{ 
    public string AccountType { get; set; } 
    public int Duration { get; set; } 
    public int DepositedAmount { get; set; } 
} 

public class AccounutManagerDAL 
{ 

    List<DatabaseRecordSimulation> dbRecords = new List<DatabaseRecordSimulation>() 
    { 
     new DatabaseRecordSimulation{AccountType="Savings",Duration=6,DepositedAmount=50000}, 
     new DatabaseRecordSimulation{AccountType="Fixed",Duration=6,DepositedAmount=50000} 
    }; 

    public List<IBankAccount> GetAllAccountsForUser(int userID) 
    { 

     List<IBankAccount> accountList = new List<IBankAccount>(); 
     foreach (DatabaseRecordSimulation dbRecrod in dbRecords) 
     { 
      IBankAccount acc = AccountFactory.GetAccount(dbRecrod); 
      accountList.Add(acc); 
     } 
     return accountList; 
    } 

} 

public static class AccountFactory 
{ 
    public static IBankAccount GetAccount(DatabaseRecordSimulation dbRecord) 
    { 
     IBankAccount theAccount = null; 
     if (String.Equals(dbRecord.AccountType, "Fixed")) 
     { 
      theAccount = new FixedAccount(); 
     } 
     if (String.Equals(dbRecord.AccountType, "Savings")) 
     { 
      theAccount = new SavingsAccount(); 
     } 
     return theAccount; 

    } 
} 
} 

阅读: 1. WCF Object Design - OOP vs SOA

回答

4

按照这个帖子: http://social.msdn.microsoft.com/Forums/eu/wcf/thread/31102bd8-0a1a-44f8-b183-62926390b3c3 你不能返回一个界面 - 你必须返回一个班级。但是,您可以创建一个抽象基类型 - BankAccount并将KnownType属性应用于它。例如:

[DataContract] 
[KnowType(typeof(FixedAccount))] 
[KnowType(typeof(SavingsAccount))] 
abstract class BankAccount { ... } 

[DataContract] 
class FixedAccount : BankAccount { ... } 

[DataContract] 
class SavingsAccount : BankAccount { ... } 

KnownType属性让我们WCF知道一些其他类型的,而不是服务合同中明确提到将成为合同的一部分。

+0

从表面上看,这看起来与问题没有任何关系,但是看起来堆栈跟踪,在我看来,即将离任的异常是一个红色的鲱鱼和序列化中发生的奇怪事情机制。你有没有考虑到你的答案?在这种情况下,这是有道理的,并得到赞扬 - 但我保留判断,你有机会随机拍摄答案。 – 2012-02-27 14:09:55

+0

@TomW当序列化失败时,您通常会遇到此类异常。我有很多次有类似的例外。 – Coder 2012-02-27 18:10:21

+1

我想象的那么多,所以信用到期。这个答案值得注意,因为初学者可能会认为这是一个连接问题并且错过了潜在的错误。 – 2012-02-27 18:12:27