【问题标题】:Exception with ServiceKnownType when the WCF method returns a collection当 WCF 方法返回集合时,ServiceKnownType 出现异常
【发布时间】:2018-02-19 18:57:13
【问题描述】:

我有一个基类 Fallible<T> 和几个派生类 Success<T>Failure<T>BadIdea<T>,它们将用于 WCF 服务调用的返回值。

正如我previously discovered 一样,为了让它工作,我需要用ServiceKnownType 属性来装饰WCF 服务方法,如下所示...

[OperationContract]
[ServiceKnownType(typeof(Fallible<Patient>)]
[ServiceKnownType(typeof(Success<Patient>)]
[ServiceKnownType(typeof(BadIdea<Patient>)]
[ServiceKnownType(typeof(Failure<Patient>)]
public Fallible<Patient> GetPatient(int id) {
  return new Success<Patient>(new Patient {ID = 1,FirstName = "Jim",Surname = "Spriggs"});
}

这很好用。但是,我现在想要一个返回集合的 WCF 服务方法...

public List<Patient> GetDischargedPatients()

按照我之前的做法,我尝试装饰它,但无论我尝试什么组合,我都会遇到异常。这是我尝试过的完整组合...

[OperationContract]
[ServiceKnownType(typeof(Fallible<PatientOverview>))]
[ServiceKnownType(typeof(Success<PatientOverview>))]
[ServiceKnownType(typeof(BadIdea<PatientOverview>))]
[ServiceKnownType(typeof(Failure<PatientOverview>))]
[ServiceKnownType(typeof(Fallible<PatientOverview[]>))]
[ServiceKnownType(typeof(Success<PatientOverview[]>))]
[ServiceKnownType(typeof(BadIdea<PatientOverview[]>))]
[ServiceKnownType(typeof(Failure<PatientOverview[]>))]
[ServiceKnownType(typeof(List<Fallible<PatientOverview>>))]
[ServiceKnownType(typeof(List<Success<PatientOverview>>))]
[ServiceKnownType(typeof(List<BadIdea<PatientOverview>>))]
[ServiceKnownType(typeof(List<Failure<PatientOverview>>))]
public Fallible<List<PatientOverview>> GetDischargedPatients() {
  return new Success<List<PatientOverview>>();
}

如你所见,我已经把所有东西都扔进去了(除了实际有效的东西!),但我仍然得到了在发现 ServiceKnownType 属性之前得到的原始异常......

“接收到http://localhost:5448/PatientsService.svc 的HTTP 响应时出错。 这可能是由于服务端点绑定未使用 HTTP 协议。这也可能是 由于服务器中止了 HTTP 请求上下文(可能是由于服务关闭 下)。有关详细信息,请参阅服务器日志。”

内部异常:

“底层连接已关闭:接收时发生意外错误。”

内部异常:

“无法从传输连接中读取数据:现有连接被强行关闭 远程主机。”

内部异常:

“现有连接被远程主机强行关闭”

WCF 确实没有给我任何关于这里出了什么问题的信息。我尝试将ServiceKnownType 与各种返回类型组合一起使用,包括Fallible&lt;Patient[]&gt;Fallible&lt;List&lt;Patient&gt;&gt;,但没有帮助。

有人知道我需要做什么才能返回一个集合吗?

【问题讨论】:

  • 您返回多少患者?可能是尺码问题!在您的情况下,您如何实现多态性?
  • @Esperadoce 我已经用一个空列表、一名患者等进行了尝试。根据我上次这样做的情况(请参阅链接的问题),问题不在于数据,而在于与序列化器无法序列化数据有关。这是它知道类型的问题,这就是我添加ServiceKnownType 属性的原因。
  • 你可以尝试在界面中制作ServiceKnowType吗?
  • 我认为你在多态序列化方面有问题我想我有一个链接可以给你,它会告诉你做这件事的路径以及你应该避免什么
  • @Esperadoce 不确定在界面中使用 ServiceKnownType 是什么意思。您使用属性标记服务调用本身,就像我在工作示例中所做的那样。这里唯一的区别是我想返回一个集合,而不是单个项目。我有兴趣看到那个链接。谢谢

标签: c# .net wcf serialization datacontractserializer


【解决方案1】:

所以我尝试使用精简版本的代码来复制您的问题,最终得到了这个

[ServiceContract]
public interface IService1
{
     //Get a patient's data
    [OperationContract]
    [ServiceKnownType(typeof(Fallible<Patient>))]
    [ServiceKnownType(typeof(Success<Patient>))]
    Fallible<Patient> GetPatient(int id);

     //Get a list of Patients
    [OperationContract]
    List<Patient> GetPatients();

    //Get a list of patients
    [OperationContract]
    [ServiceKnownType(typeof(Fallible<List<Patient>>))]
    [ServiceKnownType(typeof(Success<List<Patient>>))]
    Fallible<List<Patient>> GetSpecificPatients(string type);
}

以及服务的实现:

public class Service : IService1
{
    public Fallible<Patient> GetPatient(int id)
    {
        return new Success<Patient>() { Value = new Patient() { Name = "Scott Robinson" } };
    }

    public List<Patient> GetPatients()
    {
        List<Patient> patients = new List<Patient>();
        patients.Add(new Patient() { Name = "Scott Robinson" });
        patients.Add(new Patient() { Name = "Darryl Robinson" });
        return patients;
    }

    public Fallible<List<Patient>> GetSpecificPatients(string type)
    {
        switch (type)
        {
            case "Fallible":
                return new Fallible<List<Patient>>() { Value = new List<Patient>() { new Patient() { Name = "Scott" }, new Patient() { Name = "Darryl" } } };              
            default:
                return new Success<List<Patient>>() { Value = new List<Patient>() { new Patient() { Name = "Scott" }, new Patient() { Name = "Darryl" } } };
        }
    }
}

但是我没有得到错误。

查看您的代码,我可以看到您的 GetDiscardedPatients 返回 Fallible&lt;List&lt;PatientOverview&gt;&gt; 但没有一个“ServiceKnownTypes”属于这种类型。你试过了吗:

ServiceKnownType[Fallible<List<PatientOverview>>]
ServiceKnownType[Success<List<PatientOverview>>]
...
public Fallible<List<PatientOverview>> GetDischargedPatients() {
  return new Success<List<PatientOverview>>();
}

【讨论】:

  • 好吧,我很困惑!我确实尝试了Fallible&lt;List&lt;PatientOverview&gt;&gt; 等(不是因为我错误地输入了我编辑的答案,我在其中放置了 List>`)并且遇到了同样的问题。但是,我只是复制了您的代码并且它有效。不知道有什么区别,但它现在正在工作。非常感谢。
  • 哈哈哈 - 很高兴你成功了。如果您添加 ServiceKnownType[Fallible&lt;Patient[]&gt;],您可以破坏我的反序列化不喜欢同时具有两个属性。
  • 唯一的问题是我最初并没有同时拥有它们。我最初使用List&lt;Patient&gt;,但遇到ArrayOfPatient 的错误,这就是我切换到Patient[] 的原因。我添加到我的问题中的代码是最后一次尝试通过将所有内容都投入其中来使其正常工作!仍然不知道我做错了什么,但我不会太担心。再次感谢您的帮助
【解决方案2】:
[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(CommandServiceHelper))]
public interface IPatientService
{
     //Your interface methdos
}

这是每次 WCF 需要知道类型时将调用的帮助程序类。

public static class CommandServiceHelper
{
    public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
    {
        //Return a list of type that your service will need to know 
    }
}

如果您需要更多详细信息和解释,可以查看 Mebyon Kernow 的 this blog post

【讨论】:

  • 谢谢你,但我已经在使用那个方法了。我只使用ServiceKnownType 发布版本,以使发布的代码更易于阅读。我的问题是知道要在列表中包含哪些类型。
  • 澄清一下,我最初展示的代码可以很好地返回单个项目,但我很难确定返回集合时要包含哪些类型。
猜你喜欢
  • 2013-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多