azureserializationqueueservicebusbrokeredmessage

Azure Service Bus Queue - Serialization with BrokeredMessage


Trying to submit a queue message with an object in the message body but receiving exception on the following line with BrokeredMessage

QueueClient queueClient = QueueClient.CreateFromConnectionString(_connectionString, _queuePathName);
var data = new ABSurvey
                {
                    name = "somename",
                    version = 1,
                    language = "eng",
                    SelfSurvey = new Survey()
                    {
                        SurveyItems = new List<ISurveyItem>() { new SurveyItem(){IsSelected = true, ItemId = 1}},
                        SurveyPerception = Constants.Perception.Self
                    },
                    SelfConcept = new Survey()
                    {
                        SurveyItems = new List<ISurveyItem>() { new SurveyItem(){IsSelected = true, ItemId = 1}},
                        SurveyPerception = Constants.Perception.SelfConcept
                    }
                };
                BrokeredMessage message = new BrokeredMessage(data);
                queueClient.Send(message); 

Exception Message - Type '.Survey' with data contract name 'Survey:http://schemas.datacontract.org/2004/07/namespace' 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.

These are the models I have -

    [DataContract]
public class ABSurvey
{
    [DataMember] public string name;
    [DataMember] public int version;
    [DataMember] public string language;
    [DataMember] public ISurvey SelfSurvey;
    [DataMember] public ISurvey SelfConcept;
}

[DataContract]
public class SurveyItem : ISurveyItem
{
    [DataMember]
    public int ItemId { get; set; }
    [DataMember]
    public bool IsSelected { get; set; }
    public SurveyItem()
    {
        ItemId = -1;
        IsSelected = false;
    }
}

[DataContract]
public class Survey : ISurvey
{
     [DataMember]
    public IList<ISurveyItem> SurveyItems { get; set; }
     [DataMember]
    public Constants.Perception SurveyPerception { get; set; }
    public Survey()
    {
        SurveyItems = new List<ISurveyItem>();
    }
}

public interface ISurvey
{
    [DataMember]
    IList<ISurveyItem> SurveyItems { get; set; }
    [DataMember]
    Constants.Perception SurveyPerception { get; set; }
}
public interface ISurveyItem
{
    [DataMember]
    int ItemId { get; set; }
    [DataMember]
    bool IsSelected { get; set; }
}

Please help locate the issues.


Solution

  • You are missing [KnownType] attributes on your data contract and that is why your message can't be serialized. Detailed explanation can be found hehe.

    Simply add [KnownType] attributes to tell serializer which concrete implementation can be used:

    [KnownType(typeof(Survey))]
    [DataContract]  
    public class ABSurvey
    {
        [DataMember]
        public string name;
        [DataMember]
        public int version;
        [DataMember]
        public string language;
        [DataMember]
        public ISurvey SelfSurvey;
        [DataMember]
        public ISurvey SelfConcept;
    }
    
    [KnownType(typeof(SurveyItem))]
    [DataContract]
    public class Survey : ISurvey
    {
        [DataMember]
        public IList<ISurveyItem> SurveyItems { get; set; }
    
        public Survey()
        {
            SurveyItems = new List<ISurveyItem>();
        }
    }