【问题标题】:WCF Problem Sending Object To ClientWCF 向客户端发送对象的问题
【发布时间】:2009-11-13 19:03:23
【问题描述】:

背景

从使用 .Net Remoting 转换为 WCF。 WCF 服务器上的大多数方法都可以正常工作,但遇到了一个今天无法正常工作的方法。

这是服务合同:

[ServiceContract]
public interface IMyService
{
  [OperationContract]
  generated.Response.ACS_Response Check(generated.Request.ACS_Request request);
}

我剪掉了该接口上的其余方法,因为它们正在工作。基本上,我试图传入一个请求对象并取回一个响应对象。

ACS_Response 和 ACS_Reqeust 的类是使用 XSD.exe 针对 XSD 文件生成的。这些类驻留在 WCF 客户端和 WCF 主机都引用的 Api 程序集中。

问题

我能够调用 WCF 主机和 Request 对象,并且主机能够完成它的工作。当主机尝试返回 Response 对象时,我遇到了异常。

我打开了 WCF 跟踪并看到一个 SerializationException 说:

Type 'Api.generated.Response.ACS_ResponseQuestion'
with data contract name 'ACS_ResponseQuestion:http://...' is
not expected.  Add any types not known statically.........

问题

首先,我很困惑,因为我能够成功发送一个 Request 对象,所以看起来基础工作正常。

其次,此序列化在 .Net Remoting 下运行。这些类都是由 WSDL 生成的,所以它们不应该是可序列化的吗?

第三,主机和客户端都引用了定义这些类的同一个 Api 程序集,因此服务器和客户端都知道它们。

【问题讨论】:

    标签: c# wcf serialization


    【解决方案1】:

    我相信这是因为Api.generated.Response.ACS_ResponseQuestion 没有在合约 (API) 中使用,所以它不会自动标记为已知类型。

    阅读这些文章,他们应该解释一切:

    1. Known Types
    2. Data Contract Known Types
    3. Understanding Known Types

    快速解决方案:尝试将其添加到实现接口的类中:

    [KnownType(typeof(Api.generated.Response.ACS_ResponseQuestion))]
    

    如果这不起作用,您可能必须将其声明为ServiceKnownType

    // Define a service contract and apply the ServiceKnownTypeAttribute
    // to specify types to include when generating client code. 
    // The types must have the DataContractAttribute and DataMemberAttribute
    // applied to be serialized and deserialized. The attribute specifies the 
    // name of a method (GetKnownTypes) in a class (Helper) defined below.
    [ServiceKnownType("GetKnownTypes", typeof(Helper))]
    [ServiceContract()]
    public interface ICatalog
    {
        // Any object type can be inserted into a Hashtable. The 
        // ServiceKnownTypeAttribute allows you to include those types
        // with the client code.
        [OperationContract]
        Hashtable GetItems();
    }
    
    // This class has the method named GetKnownTypes that returns a generic IEnumerable.
    static class Helper
    {
        public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
        {
            System.Collections.Generic.List<System.Type> knownTypes =
                new System.Collections.Generic.List<System.Type>();
            // Add any types to include here.
            knownTypes.Add(typeof(Widget));
            knownTypes.Add(typeof(Machine));
            return knownTypes;
        }
    }
    
    [DataContract()]
    public class Widget
    {
        [DataMember]
        public string Id;
        [DataMember]
        public string Catalog;
    }
    
    [DataContract()]
    public class Machine : Widget
    {
        [DataMember]
        public string Maker;
    }
    

    【讨论】:

    • 向实现类添加 KnowType 属性没有帮助,但向服务契约添加 ServiceKnownType 属性确实解决了问题。 ---我仍然对为什么这是一个问题感到困惑,但至少它正在工作!谢谢!!!!!!!
    • 基本上,WCF 通过查看 ServiceContract 找出它必须序列化的所有对象。在您的情况下, ACS_ResponseQuestion 不在接口中作为参数或返回类型,这就是为什么您必须将其声明为已知类型以便序列化程序知道如何处理它的原因。
    • 呵呵呵呵呵呵,说得有道理。
    【解决方案2】:

    看看这个ServiceKnownType 提供者它应该可以为您节省一些悲伤。注册基类型非常简单,它会扫描程序集以查找从基类继承的所有类。

    【讨论】:

      【解决方案3】:

      您正在从客户端和服务器引用类,因此我建议您查看这种执行 WCF 的方式:

      http://www.dnrtv.com/default.aspx?showNum=122

      【讨论】:

      • 我很高兴地说,我遵循“GoodService”模型,为合同、主机和实施提供单独的程序集。我认为我遇到问题的地方是我传递了比“字符串”更复杂的对象。大多数复杂的对象都可以很好地传递。传递的所有对象都在我的 Api 程序集中定义。有生成的和其他的。到目前为止,我只遇到了 ACS_Response 类(及其子属性,例如 ACS_ReponseQuestion)的问题。感谢您的链接,但我想我正在做它推荐的一切。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-08
      • 2018-08-12
      • 2015-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多