WCF  使用 svcutil 生成客户端,出现下面信息:// CODEGEN: 参数“GetPlateVersionResult”需要其他方案信息,使用参数模式无法捕获这些信息。特定属性为“System.Xml.Serialization.XmlArrayAttribute”。
方法参数传递的是一个封装好的对象。返回也是一个对象。同时在 问一下WCF 服务里面能写 多少方法呢。 我写了一个服务,通过 外部类,写了很多方法,服务能开启,但是生成客户端要出现错误。  配置文件应该正确,因为我注释几个方法 ,就能生成成功。
 谢谢。  

解决方案 »

  1.   

    所有的方法都要被定义为 [OperationContract] 且方法的参数和返回值都应该是可序列化的,即定义为[DataContract]或者[Serialize]或者[XmlSerialize]明确表示序列化内容的。另外,WCF不能有方法重名(重载的不行)
      

  2.   

    暴露出去得wcf服务需要服务契约 [servercontract]该契约放在class前或者interface前。
    而后[operationcontract]是操作契约,需要放在方法前面。而后操作的class需要[datacontract]数据契约,而后要暴露的属性用[datamember]标记。所有过程完成,wcf不会出问题。后面再web.config中配置endpoint节点即可。配置的时候需要指向namespace.Class还有接口。address可以为空,部署后address为IIS下的svc服务路径。只需要配置好服务器端services的service,behavior,endpoint。形如:
      <system.serviceModel>
      <services>
      <service behaviorConfiguration="" name="Artech.WindowsFormHostingDemo.Services.CalculatorService">
      <endpoint address="" binding="basicHttpBinding"
      bindingConfiguration="" contract="Artech.WindowsFormHostingDemo.Contracts.ICalculator" />
      </service>
      </services>
      </system.serviceModel>
      

  3.   

       <system.serviceModel>
            <behaviors>
                <serviceBehaviors>
                    <behavior name="">
                        <serviceMetadata httpGetEnabled="true" />
                        <serviceDebug includeExceptionDetailInFaults="false" />
                    </behavior>
                </serviceBehaviors>
            </behaviors>
            <services>
                <service name="命名空间.类名">
                    <endpoint address="" binding="wsHttpBinding" contract="命名空间.接口名">
                        <identity>
                            <dns value="localhost" />
                        </identity>
                    </endpoint>
                    </service>
            </services>
        </system.serviceModel>
     
      

  4.   


    谢谢。 我 是那样定义的,而且我做实验成功来的。但是我封装一个对象,里面有 object 类型。如下:
     服务契约--------------------------------------------------------------
            /// <summary>
            /// 增加一条记录
            /// </summary>
            /// <param name="requestData">封装类型,对象</param>
            /// <returns></returns>
            [OperationContract]
            [FaultContract(typeof(ExceptionClass))]
            int Common_AddObject(RequestData requestData);
      实现:-------------------------------------------------------------
            public int Common_AddObject(RequestData requestData)
            {
                try
                {
                    MDSystem.BLL.ICommonAccessService common = (MDSystem.BLL.ICommonAccessService)Assembly.Load(AssemblyPath).CreateInstance("MDSystem.BLL." + requestData.Type);
                    return common.Add(requestData.RequestObject);
                }
                catch (Exception ex)
                {
                    MDSystem.Model.ExceptionClass exceptionClass = GetExceptionClassAndWriteLog(ex, "Common_AddObject");
                    FaultCode faultCode = new FaultCode(ex.Message);
                    FaultReason faultReason = new FaultReason(ex.Source);
                    throw new FaultException<MDSystem.Model.ExceptionClass>(exceptionClass, faultReason, faultCode);            }
            }
      RequestData 封装类-----------------------------------------------------------------
                [DataContract]
        [KnownType("GetKnowType")]
        public class RequestData
        {
            public RequestData() { }
            public RequestData(object obj)
            {
                this.requestObject = obj;
            }
            [DataMember]
            public object RequestObject
            {
                get { return requestObject; }
                set { requestObject = value; 
                }
            }
            [DataMember]
            public string Type
            {
                get { return type; }
                set { type = value; }
            }
            private static Type[] GetKnowType()
            {
                return Assembly.Load("MDSystem.Model").GetTypes();
            }
    我 能运行,但是用 svcutil 工具生成出来,有这样提示:
          // CODEGEN: 参数“GetPlateVersionResult”需要其他方案信息,使用参数模式无法捕获这些信息。特定属性为“System.Xml.Serialization.XmlArrayAttribute”
           自己觉的是序列化问题,但找不出原因。  再次谢谢   你们哈。 
      

  5.   

    [DataMember]
      public object RequestObject
      {
      get { return requestObject; }
      set { requestObject = value;  
      }这个地方定义了 object ?为什么不明确类型呢?定义个基类也好呀。
    如果是我,我会尽可能定义POJO的类型作为参数和返回值。关于参数和返回值,推荐你看下:
    http://www.cnblogs.com/artech/archive/2007/03/10/669874.html
      

  6.   

    object是所有类型的基类,它没有提供具体的Xml序列化方法,所以你序列化失败。
      

  7.   

    谢谢 大家哈。用 TCP服务能正确用。  只是用vs 2008 和用 svcutil工具生成的代码不同。 主要问题是,我传递一个对象,里面有时间属性,但是在服务端不能接收到 时间,时间属性一直是默认值,其他属性值我能正确接收。还有就是svcutil工具生成的代码 出现  这种提示:
        // CODEGEN: 参数“GetPlateVersionResult”需要其他方案信息,使用参数模式无法捕获这些信息。特定属性为“System.Xml.Serialization.XmlArrayAttribute”。
       
         我感觉是 序列化错误,导致参数不能正确接收,但是不知道具体是为什么,会出现    这种信息“// CODEGEN: 参数“GetPlateVersionResult”需要其他方案信息,使用参数模式无法捕获这些信息。特定属性为“System.Xml.Serialization.XmlArrayAttribute”。”     还有一个问题,我通过外部接口 和 类 ,声明了很多操作契约,和操作契约实现。服务能够正确启动,但是生成客户端代码错误。注释几个契约服务生成客户端代码又正确。 以前的客户端能够调用服务。
     谢谢大家... 
      

  8.   

    但是我没有用  xml 序列化啊 。不是用 数据契约,什么类型都可以吗。难道是我理解错了。
      

  9.   

     因为这里我封装了一个通用的方法。 我不知道它是什么具体的类,或者是其他。我只能通过,封装对象的Type 去反射出,所要调用的业务层,在把 object 转化 到对应的实体,或者 int ,string 或者其他....
      

  10.   

    我也没有试验过,用object确实有很多类型安全的问题,此外服务器端有的类型,客户端未必有。
      

  11.   

    虽然有了 KnowType,但是 object 的参数,序列化是否真正支持?表示怀疑。另外,看你的错误提示,貌似有个返回是 Array 的方法?
      

  12.   


    谢谢你的回答。  用object封装应该是没问题的。因为我做过实验,方法的返回值没有 Array ,我只是返回了List集合,和字典,和其他 类型。这些我在网上看 了,都是支持的,而且也能运行成功,只是 用 svcutil 和 vs2008 生成的客户端代码不同,  svcutil多生成了 “System.Xml.Serialization.XmlArrayAttribute”。  程序能运行,但是如果契约过多就不能生成客户端。  用 的是 TCP 
      

  13.   

    lz把用于元数据交换的wsdl贴出来看看,我手头没法测试,顺便等一下fangxinggood同志实验的结果。另外可以先配置为http协议,看看究竟序列化成什么了。
      

  14.   

    谢谢。。 我改成http 试试。
      

  15.   

    OK,的确可以。不过不是很负责的场景。1.契约namespace WcfSerializerTest
    {
        [ServiceContract]
        public interface IService1
        {
            [OperationContract]
            RequestData AddObject(RequestData request);
        }    [DataContract]
        [KnownType("GetKnowType")]
        public class RequestData
        {
            private object requestObject;
            private string type;
            public RequestData() { }
            public RequestData(object obj)
            {
                this.requestObject = obj;
            }
            [DataMember]
            public object RequestObject
            {
                get { return requestObject; }
                set { requestObject = value; }
            }
            [DataMember]
            public string Type
            {
                get { return type; }
                set { type = value; }
            }
            private static Type[] GetKnowType()
            {
                var assmbly = Assembly.GetExecutingAssembly();
                var types = assmbly.GetTypes();
                List<Type> dataContracts = new List<Type>();
                foreach (var t in types)
                {
                    var atts = t.GetCustomAttributes(typeof(DataContractAttribute), true);
                    if (atts.Length > 0)
                        dataContracts.Add(t);
                }
                return dataContracts.ToArray();
            }
        }
    }
    2.服务实现
    namespace WcfSerializerTest
    {
        public class Service1 : IService1
        {
            #region IService1 Members
            public RequestData AddObject(RequestData request)
            {
                var type = request.RequestObject.GetType();
                var mi = type.GetMethod("GetInstance", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
                var obj = mi.Invoke(null, new object[] {request.RequestObject});
                return new RequestData { RequestObject = obj };
            }
            #endregion
        }
    }3.Client调用class Program
    {
        static void Main(string[] args)
        {
            var client = new MySvc.Service1Client();
            var request = new MySvc.RequestData();
            request.RequestObject = new MySvc.MyClass1 { Id = "clientTest1", Name = "nameTest1" };
            var data = client.AddObject(request);
            Debug(data.RequestObject);        request.RequestObject = new MySvc.MyClass3 { SomeDay = new DateTime(2011, 3, 1) };
            data = client.AddObject(request);
            Debug(data.RequestObject);
            Console.Read();
        }    static void Debug(object obj)
        {
            var type = obj.GetType();
            var properties = type.GetProperties();
            Array.ForEach(properties, t => Console.WriteLine("{0}:{1}", t.Name, t.GetValue(obj, null)));
        }
    }
      

  16.   

    4. Model 的一堆小类namespace WcfSerializerTest.Model
    {
        [DataContract]
        public class MyClass1
        {
            [DataMember]
            public string Id { get; set; }
            [DataMember]
            public string Name { get; set; }        internal static MyClass1 GetInstance(MyClass1 clientObj)
            {
                return new MyClass1 { Id = "MyClass1Id_" + Guid.NewGuid().GetHashCode(), Name = clientObj.Name};
            }
        }
        [DataContract]
        public class MyClass2
        {
            [DataMember]
            public string Id { get; set; }
            [DataMember]
            public string Code { get; set; }        internal static MyClass2 GetInstance(MyClass2 clientObj)
            {
                return new MyClass2 { Id = "MyClass2Id_" + Guid.NewGuid().GetHashCode(), Code = clientObj.Code};
            }
        }
        [DataContract]
        public class MyClass3
        {
            [DataMember]
            public string SomeProperty { get; set; }
            [DataMember]
            public DateTime SomeDay { get; set; }        internal static MyClass3 GetInstance(MyClass3 clientObj)
            {
                return new MyClass3 { SomeProperty = "SomeProperty_" + Guid.NewGuid().GetHashCode(), SomeDay = clientObj.SomeDay };
            }
        }
    }
    测试了下,客户端通过KnowType可以生成所有的服务端声明的元数据类型:MyClass1 - 3
    时间属性传值也正常。输出:SomeDay是我从客户端传过去的,又从服务端回传回来的
    ExtensionData:System.Runtime.Serialization.ExtensionDataObject
    Id:MyClass1Id_831466049
    Name:nameTest1ExtensionData:System.Runtime.Serialization.ExtensionDataObject
    SomeDay:3/1/2011 12:00:00 AM
    SomeProperty:SomeProperty_-1701593304
      

  17.   


    谢谢。 那样应该是对的, 但是我现在的问题是 , 我用vs2008 和 svcutil 生成的代码不相同,
       用svcutil生成的 如下:
         // CODEGEN: 参数“GetPlateVersionResult”需要其他方案信息,使用参数模式无法捕获这些信息。特定属性为“System.Xml.Serialization.XmlArrayAttribute”。
        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ISystemServices/GetPlateVersion", ReplyAction="http://tempuri.org/ISystemServices/GetPlateVersionResponse")]
        [System.ServiceModel.FaultContractAttribute(typeof(MDSystem.Model.ExceptionClass), Action="http://tempuri.org/ISystemServices/GetPlateVersionExceptionClassFault", Name="ExceptionClass", Namespace="http://schemas.datacontract.org/2004/07/MDSystem.Model")]
        [System.ServiceModel.XmlSerializerFormatAttribute()]
        [System.ServiceModel.ServiceKnownTypeAttribute(typeof(SysNode))]
        [System.ServiceModel.ServiceKnownTypeAttribute(typeof(CustomPropertyValueDataTable))]
        [System.ServiceModel.ServiceKnownTypeAttribute(typeof(FeaturePageRegistraPermissionTable))]
    实体比较多。   还有就是我用  partial  把 契约 和 实现类分成 不同的文件存放, 如果方法多了就不能生成客户端代码,服务能正常运行。 
      

  18.   

    vs  2008 直接引用 服务  生成的代码没有  [System.ServiceModel.XmlSerializerFormatAttribute()]。我就感觉是不是序列化错了,或者是我那理写错了。 但 找不出原因, 服务能正常运行。 谢谢。大家了。 
      

  19.   

    如果方法多了就不能生成客户端代码
    ----------
    异常信息提示是什么?vs 2008 直接引用 服务 生成的代码没有 [System.ServiceModel.XmlSerializerFormatAttribute()]。
    ----------
    svcutil 语句贴出来看看。
      

  20.   

    看生成的代理,你用的序列化器不一样。你在契约里可能有这样的标识:[XmlSerializerFormat]
      

  21.   


    首先要谢谢你哈。  svcutil   语句  : svcutil net.tcp://IP:6666 方法多时错误如下 :Error: Cannot obtain Metadata from net.tcp://10.100.100.66:1888/If this is a Windows (R) Communication Foundation service to which you have acce
    ss, please check that you have enabled metadata publishing at the specified addr
    ess.  For help enabling metadata publishing, please refer to the MSDN documentat
    ion at http://go.microsoft.com/fwlink/?LinkId=65455.
    WS-Metadata Exchange Error
        URI: net.tcp://10.100.100.66:1888/    元数据包含无法解析的引用:“net.tcp://10.100.100.66:1888/”。    没有终结点在侦听可以接受消息的 net.tcp://10.100.100.66:1888/。这通常是由于不
    正确的地址或者 SOAP 操作导致的。如果存在此情况,请参阅 InnerException 以了解详细
    信息。
     
      

  22.   


    谢谢。 但是我在我项目里查找了一下没有  xml  序列化的东西。 是我svcutil语句错了吗。 还是其他 。
      

  23.   

    还是看不除了有什么问题,这样下去也没有结果啊单把IMetadataExchange换成mexHttpBinding试试如何?
      

  24.   

    首先 谢谢大家,
     我发现问题,但不知道是不是这个问题。我认为出现原因是我传递了 dataSet ,用svcutil生成客户端代码 才出现这种异常信息(// CODEGEN: 参数“GetPlateVersionResult”需要其他方案信息,使用参数模式无法捕获这些信息。特定属性为“System.Xml.Serialization.XmlArrayAttribute”。)  用vs添加服务正确。    但 wcf 是支持dataSet 传递的,我不知道为什么 用svcutil 生成出错。
     
    svcutil 语句: svcutil  net.tcp://ip:端口     。
     
    希望谁能给我解答一下。  谢谢。
      

  25.   

    你这个问题可以到 msdn 的 wcf 论坛再问问看。http://social.microsoft.com/Forums/zh-CN/wcfzhchs/threads