3

I had a WCF Service with an operation contract as

void AddQuery(IQuery Query);

My IQuery is like this

public interface IQuery
{
    Guid                Id { get; set; }        
    string              QueryNo { get; set; }
    string              Status { get; set; }
    IData               data { get; set; }
}

and the implementation of IQuery is in

[Serializable]
public class Query : IQuery
{
    Guid                Id { get; set; }        
    string              QueryNo { get; set; }
    string              Status { get; set; }
    IData               data { get; set; }
}

When i am trying to send my object from client as

  public void AddQuery(IQuery query)
  {
      try
      {
          // I am sure that the query object is not null and it is implemented
          objServiceClient.AddEnquiry(query);
      }
      catch (Exception ex)
      {
      }
  }

But i am getting an exception as

There was an error while trying to serialize parameter . The InnerException message was 'Type 'ViewModels.Query' with data contract name 'Query:http://schemas.datacontract.org/2004/07/ViewModels' 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.

Could anyone suggest me what will be the resolution for this error?

Mormegil
  • 7,955
  • 4
  • 42
  • 77
Bhuvan
  • 419
  • 1
  • 11
  • 25

1 Answers1

5

Consider serializing concrete classes. You cannot serialize interfaces . Refer to this answer: https://stackoverflow.com/a/4659289/860243

Some useful links I found from bing:

http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/

The above article discusses your situation and examples of using [KnownType] for your derived classes

Update:

Based on this link, please check the below update:

public interface IQuery 
{ 
    Guid Id { get; set; }
    string QueryNo{ get; set; } 
    string Status { get; set; } 
    IData data {get; set;}
}

Your Query class using Data contract serializer implementing your interface IQuery

[DataContract]
public class Query : IQuery
{
    [DataMember]
    public Guid Id { get; set; };
    [DataMember]
    public string QueryNo { get; set; };
    [DataMember]
    public string Status { get; set; };
    [DataMember]
    public Data data { get; set; }; //Make sure you serialize Data class as well
}

And for your service contract:

[ServiceContract]
public interface IMyQueryService
{
      [OperationContract]
      [ServiceKnownType(typeof(Query))]
      void AddQuery(IQuery query);
}

The [ServiceKnownType(typeof(Query))] will enable your operation contract to allow Query as input. Also please note you need to specify all your IQuery implementations that needs to be passed as parameters to your Operation contract with ServiceKnownType attribute .

Also if you want more than one (or all) operation contract to take them as parameters, specify the ServiceKnownType attribute for ServiceContract instead of each operation contract separately.

Hope this helps!

Community
  • 1
  • 1
Flowerking
  • 2,551
  • 1
  • 20
  • 30
  • Hi but when i am sending, i am implementing my method as IQuery obj = new Query(); where i am upcasting my obj with Query class. because i need to change a lot of change in my code if i want to use concrete class. Do we have any other solution? – Bhuvan Feb 04 '13 at 16:26
  • Yes, You Can create base class (concrete not abstract) and use it to derive your other classes. But you need to tell the WCF serializer explicitly that your derived classes are KnownTypes of your base class by using `[KnownType]` attribute over your base class. For this better use DataContract Serialization instead of XmlSerializer – Flowerking Feb 04 '13 at 16:32
  • could you please suggest me a sample of using DataContractSerializer especially in my code? or a link in DataContractSerializer – Bhuvan Feb 04 '13 at 16:36
  • Hi if use this DataContractSerializer wll my existing interface concept works? or do i need to still change implementations of my operation contract interface implementation to concrete classes? – Bhuvan Feb 04 '13 at 16:56
  • Please Check [this](http://stackoverflow.com/questions/153775/wcf-and-interfaces-as-parameters) - Hmm.. looks like there is a way to pass interface as parameter for your opetation contract! – Flowerking Feb 04 '13 at 17:02
  • You should not send an Interface on client side, you have to send the concrete class that implements your interface from client. But you can use Interface as parameter for your operation contract for the service. – Flowerking Feb 05 '13 at 09:14
  • You are right. i solved this. i slightly i edited ur answer to acheive the task – Bhuvan Feb 05 '13 at 11:44
  • @Bhuvan I have checked your edit, and I doubt you need to do that, may be your implementation code is different. I don't think you need to do `KnownType(typeof(IQuery))` on the concrete class! – Flowerking Feb 05 '13 at 11:57
  • Hi Flowerking, i followed this blog "http://blogs.msdn.com/b/domgreen/archive/2009/04/13/wcf-using-interfaces-in-method-signatures.aspx". As per this blog i need mention the known type of my Interface in a concrete class – Bhuvan Feb 05 '13 at 12:21
  • I cannot open your link, its saying "access denied". But to tried to create a demo program without `KnownType(typeof(IQuery))` on the concrete class and it's working just fine! – Flowerking Feb 05 '13 at 13:17