إجابة مقترحة "ServiceKnownType" attribute is missing from generated file

  • 05/شوال/1428 02:26 م
     
     

    Hi

    becuase of complex type in service params (in,out) I had to decorate the service Operation contract with "ServiceKnownType" attribute.

    The problem is that when i heat add service refference to generate proxi class that attribute dows' t apear in generated interface.

     

    when I run the app it throw exeption about known type.

     so i added it manualy and every thing work...

     

    of course that every time i doing update web refference i have to do it again.

     

    any short cut idea?

     

    thanks

جميع الردود

  • 05/شوال/1428 08:35 م
     
     

    Can you post a small sample of the ServiceContract and KnownTypes that reproduces the issue?

  • 16/شوال/1428 12:17 م
     
     

    Hi, sorry for delay

    here is some code. base on clean wcf project with some changes marked with color

    contract

     

    [ServiceContract]

    public interface IService1

    {

    [OperationContract]

    string GetData(int intParam);

     

    [OperationContract]

    [ServiceKnownType (typeof(CompositeType))]

    Dictionary<string,object> GetDataUsingDataContract(CompositeType composite);

    }

     

    implement

    public Dictionary<string,object> GetDataUsingDataContract(CompositeType composite)

    {

    Dictionary<string, object> res = new Dictionary<string, object>();

    res.Add("Third", new CompositeType { BoolValue = false, StringValue = "Hi" });

    return res;

    }

     

    client

    static void Main(string[] args)

    {

    ServiceReference.Service1Client proxy = new Client.ServiceReference.Service1Client();

    Dictionary<string,object> obj = proxy.GetDataUsingDataContract(null);

    }

     

    now when running I get an exeption with that message :

     

    The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:GetDataUsingDataContractResult. The InnerException message was 'Error in line 1 position 573. Element 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:Value' contains data of the 'http://schemas.datacontract.org/2004/07/Server:CompositeType' data contract. The deserializer has no knowledge of any type that maps to this contract. Add the type corresponding to 'CompositeType' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'.  Please see InnerException for more details.

     

    to fix it I need to add manualy to reference.cs (hidden in solution explorer) under service reference->MyService->Reference.svcmap->reference.cs

    in the IService1 section that attribute:

     

    [ServiceKnownType(typeof(CompositeType))]

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService1/GetDataUsingDataContract", ReplyAction="http://tempuri.org/IService1/GetDataUsingDataContractResponse")]System.Collections.Generic.Dictionary<string, object> GetDataUsingDataContract(Client.ServiceReference.CompositeType composite);

     

    and it work correct.

     

    thanks

    Adiel

    • تم الاقتراح كإجابة بواسطة lboeldt 19/صفر/1433 04:55 م
    • تم إلغاء اقتراح كإجابة بواسطة lboeldt 19/صفر/1433 04:55 م
    •  
  • 19/صفر/1433 05:10 م
     
     إجابة مقترحة يتضمن تعليمات برمجية

    Hi I came across your article because I had the same problem. A few search results down on Google linked to a blog post that solved the problem for me.

    http://softwareblog.alcedo.com/2010/01/default.aspx

    Basically the blog boils down to this.

    When making a class for WCF, DO NOT:

    [DataContract]
    class wxyz
    {
            List<T> _var = new List<T>();
    
            [DataMember]
            public IList<T> Var
            {
                get { return _var; }
            }
    
    // rest of your code...
    }
    

    DO this instead

    [DataContract]
    class wxyz
    {
            List<T> _var;
    
    	public wxyz() { Initialize(); }
    
    
    	[OnDeserializing]
    	private void OnDeserialize()
    	{
    	    Initialize();
    	}
    
    
    	private void Initialize()
    	{
    	    _var = new List<T>();
    	}
    
    
            [DataMember]
            public IList<T> Var
            {
                get { return _var; }
            }
    
    // rest of your code...
    }
    

    I guess to put it bluntly: the problem is that objects, generics and lists are not implicitly created during deserialization (and are thus null on serialzation). So you have to explicitly create them by using the [OnDeserialization] tag, which I guess is some sort of event trap. It worked for my situation, let me know if it works for yours.


     

     

    • تم الاقتراح كإجابة بواسطة lboeldt 19/صفر/1433 05:10 م
    •