3

I am using Stream object inside my wcf Contracts so forced to use MessageContract instead of DataContract.

 [MessageContract]
    public class Document 
    {
        [MessageBodyMember(Order = 1)]
        public System.IO.Stream FileData;

}

 [MessageContract]
    public class A : Document 
    {
        [MessageBodyMember]
        public string input;

}

 [MessageContract]
    public class B : Document 
    {
        [MessageBodyMember]
        public string someProp;

}

[ServiceContract]
    public interface ISomeService
    {

        [OperationContract]
        Document SomeMethod(Document file);
}

I want the consumer of this service to create object of either A or B and call the service with it. On the service side, I can type cast it to proper object then perform some action.

Problem is I cannot specified KnownType with MessageContract and inherited contracts cannot be exposed to client until they are used in service or declared with KnownType.

I tried google it but couldn't find anything related to KnownType with MessageContract.

As suggested in comment... i updated my message contract with KnownType but they are still not exposed to client through service reference...

[MessageContract]
    [KnownType(typeof(FileSystemStoredDocument))]
    [KnownType(typeof(FileBoundStoredDocument))]
    [KnownType(typeof(SharepointStoredDocument))]

    public class Document : DocumentInfo, IDisposable
    {
}

Can any one help me what's wrong here?

Note: ALL KnownType are inherited from Document

Draken
  • 3,134
  • 13
  • 34
  • 54
Abhash786
  • 881
  • 2
  • 24
  • 53
  • What you are saying seems wrong to me. AFAIK you can sure use `KnownType` on `MessageContract`. But i do believe to remember, streams are not Serializable, wich means you will not be able to transfer them. Also have a look at [this](http://stackoverflow.com/questions/3208866/wcf-message-contract-and-streaming) – lokusking Jul 16 '16 at 17:30
  • Can you post the exception? Also, did you mark `DocumentInfo` as known-type too? – lokusking Jul 19 '16 at 07:36
  • There is no exception. I can't simple see derived types in proxy generated code. and Document info is not mentioned as knownType as it is already part of one of the method in service contract. – Abhash786 Jul 19 '16 at 09:13

1 Answers1

4

Message contracts describe exactly how the message should look like. They do support inheritance, but you must specify the exact message contract you're using in a specific operation.

If you check the body parts of the message:

ContractDescription.GetContract(typeof(ISomeService)).Operations[0].Messages[0].Body.Parts

You'll see exactly one part - a Stream object. That's in contrast to data contracts, where the body contains a part of the type Object. So you see why KnownType wouldn't work here.

(The ContractDescription class is used, among other things, to generate WSDL. See the WsdlExporter class.)

What you can do is create a hierarchy of data contracts that would be contained in the message contract, e.g.

[MessageContract]
public class Document 
{
    [MessageHeader]
    public DocumentProperties Properties;

    [MessageBodyMember(Order = 1)]
    public System.IO.Stream FileData;
}

[DataContract]
[KnownType(typeof(A))]
[KnownType(typeof(B))]
public abstract class DocumentProperties { }

[DataContract]
public class A : DocumentProperties 
{
    [DataMember]
    public string input;
}

[DataContract]
public class B : DocumentProperties 
{
    [DataMember]
    public string someProp;
}

Note that you you cannot have more than one body member if you want to pass a Stream, so the rest of the properties must be in headers.

Eli Arbel
  • 22,391
  • 3
  • 45
  • 71