c# - WCF 类型问题?

标签 c# wcf serialization types

当我调用我的 WCF Soap 服务的方法时,抛出一个错误,并且 svlog 文件中出现一个错误:

Type 'xxx.ActiveDirectoryService.classes.WCF.Message' with data contract name 'Message:http://schemas.datacontract.org/2004/07/xxx.ActiveDirectoryService.classes.WCF' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

我尝试在这里和那里使用 KnownType 但没有成功(我必须承认我不太确定我是否 100% 正确地使用了它)。

这是我的接口(interface)/类:

[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
    }
}

编辑: 12AM35 GMT+1

我添加了 Dummy() 方法。

  • 从客户端调用 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

编辑: 13AM31 GMT+1

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

最佳答案

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

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

尝试添加这个:

[ServiceContract]
[ServiceKnownType(typeof(Message))]
public interface IActiveDirectory
{
    ...
}

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

这也应该有效:

[DataContract]
[KnownType(typeof(Message))]
public abstract class AbstractMessage
{
    ...
}

因为您想告诉数据协定序列化程序Message 是已知类型的AbstractMessage

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

你说:WCF + 多态性有点奇怪......

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

查看我的 answer here有关如何传递已知类型知识的详细信息,请通过 KnownTypes , ServiceKnownTypes或配置。

关于c# - WCF 类型问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17144861/

相关文章:

c# - 业务对象是否应该具有行为?

java - JBoss EAP 更新到 7.2.1 后如何处理 WELD-001477?

c# - JSON 反序列化为泛型

C# 简单图像调整大小 : File Size Not Shrinking

c# - JSonConverter 如何进行泛型反序列化

c# - "good"这个方法是怎么产生随机数的?

c# - 多个 Entity Framework 表破坏 WCF

wcf - 调试 WCF 服务的工具

mysql - 在字段中查找字符串的特定部分并将其替换为反斜杠

c# - 在 C# 中没有等效项的 Java 语言功能