Исключение WCF при возврате списка объектов интерфейса - PullRequest
1 голос
/ 27 февраля 2012

Я получаю следующее исключение при вызове службы WCF с веб-сайта ASP.NET.Как мы можем преодолеть это?

Примечание. Применяя точку останова в сервисном проекте, я проверил, что сервис возвращает два допустимых объекта.

Примечание: В сервисе я получаю список 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 - ООП против SOA

1 Ответ

4 голосов
/ 27 февраля 2012

Согласно этому сообщению: 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 знать, что какой-то другой тип, явно не указанный в договоре на обслуживание, будет частью договора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...