WCF有类型的问题吗?

Ser*_*rge 6 c# wcf serialization types

当我调用我的WCF Soap服务的方法时,会抛出错误并在svlog文件中显示错误:

输入数据协定名称为"消息:http://schemas.datacontract.org/2004/07/xxx.ActiveDirectoryService.classes.WCF "的"xxx.ActiveDirectoryService.classes.WCF.Message" .考虑使用DataContractResolver或将任何静态未知的类型添加到已知类型列表中 - 例如,通过使用KnownTypeAttribute属性或将它们添加到传递给DataContractSerializer的已知类型列表中.

我试图在这里和那里使用KnownType但没有成功(我必须承认我不太确定我100%正确使用它).

这是我的接口/类:

[ServiceContract]
public interface IActiveDirectory
{
    [OperationContract]
    [WebGet]
    void Dummy();

    [OperationContract]
    [WebGet]
    AbstractMessage Dummy2();

    [OperationContract]
    [WebGet]
    AbstractMessage Dummy3();

    [OperationContract]
    [WebGet]
    AbstractMessage SetPassWord(string customer, string customerPassword, string userLogin, string userPassword);
}

[DataContract]
public abstract class AbstractMessage
{
    [DataMember]
    public virtual bool IsError { get; set; }

    [DataMember]
    public virtual string ErrorMessage { get; set; }

    [DataMember]
    public virtual string ReturnValue { get; set; }
}

public class Message : AbstractMessage
{
<...>
}


[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
[KnownType(typeof(AbstractMessage))]
public class ActiveDirectory : IActiveDirectory
{
    public void Dummy()
    {
    }

    public AbstractMessage Dummy2()
    {
        return new AbstractMessage();
    }

    public AbstractMessage Dummy3()
    {
        return new Message();
    }

    public AbstractMessage SetPassWord(string customer, string customerPassword, string userLogin, string userPassword)
    {
    <...>

        return message; // message is of type Message
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑: 12AM35 GMT+1

我添加了Dummy()方法.

  • 从客户端调用虚拟工作正常.
  • 从客户端调用Dummy2工作正常.
  • 从客户端调用Dummy3会导致相同的错误.

编辑 12AM39 GMT+1

进行以下更改没有帮助.

[DataContract]
[KnownType(typeof(AbstractMessage))]
public class Message : AbstractMessage

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
[KnownType(typeof(AbstractMessage))]
[KnownType(typeof(Message))]
public class ActiveDirectory : IActiveDirectory
Run Code Online (Sandbox Code Playgroud)

编辑: 13AM31 GMT+1

如果我将Dummy3返回类型设置为Message,则在客户端代码中调用Dummy3会起作用.
WCF +多态性有些奇怪......

Sam*_*der 4

您的 WCF 服务需要返回 DTO。这些不能是接口,如果您想返回抽象基类,那么您将需要告诉数据协定序列化器您实际上打算返回这些类型的哪些实现。

它已经知道 AbstractMessage 类型(作为操作契约的一部分),但是在操作契约中未显式声明的该类型的所有实现都应该在已知类型中声明。

尝试添加这个:

[ServiceContract]
[ServiceKnownType(typeof(Message))]
public interface IActiveDirectory
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

在这里,您告诉数据协定序列化器该服务可以返回(或期望)类型的对象Message作为其方法的参数。

这也应该有效:

[DataContract]
[KnownType(typeof(Message))]
public abstract class AbstractMessage
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

正如您想告诉数据契约序列化器的那样,这Message是一种已知类型AbstractMessage

我相信您的更改不起作用,因为您在服务上使用 KnownTypes 而不是 ServiceKnownTypes 并且您尝试在派生类而不是父类上应用已知类型,这就是您在语言中习惯做的事情(消息是AbstractMessage),但在 WCF 中,您必须将其翻转并将派生实现放在父类上(AbstractMessage 具有实现 Message),这可能是有限制的。

你说:There 's something odd with WCF + Polymorphism...

相信我,最好不要认为 WCF 支持多态性,因为它不支持。您只需返回 DTO,如果您想尝试使这些多态,您将遇到很多问题。多态性是通过接口实现的,在WCF中不能使用接口。如果您使用抽象类,那么由于 c# 中缺乏多重继承,您很快就会意识到 DTO 只能表示对象的单个视图,并且无法创建表示域模型类的多个接口的 DTO。(请参阅有关该主题的问题)

请参阅我的答案,了解如何通过KnownTypesServiceKnownTypes或配置传递已知类型的知识的详细信息。