locked
Can we have the "Encoding" type as a property in Data Contract in WCF? RRS feed

  • Question

  • User-2024402007 posted

    I have a requirement where I need to have the property "Encoding" as Data Contract. The Client would be sending "Encoding type" in that, which the service uses for processing the data.

       [DataContract]
        public class EncodingClass
        {
            [DataMember]
            public Encoding Encodingtype { get; set; }
        }

    But I get an exception as below,

    "The InnerException message was 'Type 'System.RuntimeType' with data contract name 'RuntimeType:http://schemas.datacontract.org/2004/07/System' 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'. Please see InnerException for more details."

    Please suggest how can this be made work or is this right way to approach.

        

    Tuesday, August 11, 2020 11:22 AM

All replies

  • User-1330468790 posted

    Hi Gowthambe91,

     

    The error message already provides you with two options:

    1.  using the KnownTypeAttribute attribute
    2. adding them to the list of known types passed to DataContractSerializer

    However, the error message you posted is not related to the class you gave since the error tells that you are using the Type as the property/member. That way, you may need to refer to this: WCF Exception on Member of type “Type”

     

    I would like to introduce the underlying reason for the exception.

    If you are using the class "EncodingClass" to serialize or deserialize, you will still get a similar error since this class has a property of type that is not a run-time type but serialization is done using run-time types.

    [DataContract]
    public class EncodingClass
    {
    	[DataMember]
    	public Encoding Encodingtype { get; set; }
    }

    The underlying framework try to load all the relevant run-time types BEFORE actual serialization. In your case, you might need to let the serializer know what the type Encoding is. 

    For example, 

    • Using KnownTypeAttribute
    static void Main(string[] args)
            {
                EncodingClass encodingClass = new EncodingClass() {  Encodingtype=Encoding.UTF8};
               
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(EncodingClass));
    
                string result;
                using (var ms = new MemoryStream())
                {
                    serializer.WriteObject(ms, encodingClass);
                    result = Encoding.Default.GetString(ms.ToArray());
                };
    
                Console.WriteLine(result);
    
                Console.ReadLine();
    
    
            }
    
            [KnownType(typeof(UTF8Encoding))]
            [KnownType(typeof(DecoderReplacementFallback))]
            [KnownType(typeof(EncoderReplacementFallback))]
    
            [DataContract]
            public class EncodingClass
            {
                [DataMember]
                public Encoding Encodingtype { get; set; }
            }
    • adding them to the list of known types passed to DataContractSerializer
    static void Main(string[] args)
            {
                EncodingClass encodingClass = new EncodingClass() {  Encodingtype=Encoding.UTF8};
                DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings()
                {
                    KnownTypes = new Type[] { 
    typeof(UTF8Encoding),
    typeof(DecoderReplacementFallback),
    typeof(EncoderReplacementFallback)
    } }; DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(EncodingClass), settings); string result; using (var ms = new MemoryStream()) { serializer.WriteObject(ms, encodingClass); result = Encoding.Default.GetString(ms.ToArray()); }; Console.WriteLine(result); Console.ReadLine(); } [DataContract] public class EncodingClass { [DataMember] public Encoding Encodingtype { get; set; } }

    Both ways work.

     

    Hope this can help you.

    Best regards,

    Sean

    Wednesday, August 12, 2020 5:25 AM