Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF OperationContract with loosely typed parameter

I want a loosely typed parameter in my web method.

I have a scenario where the client can send any of 25 DataContract objects into the WCF operation e.g.

proxy1.myFunction(PersonObject)
proxy1.myFunction(ComputerObject)

My restriction is there should be only one Operation Contract exposed to the client.

How can I design a web method which can take any of the 25 DataContract classes as a parameter? I tried with object as type of parameter and gave KnownType attribute to the DataContract classes but I had no luck during the serialization process.

like image 636
user1312242 Avatar asked Jan 17 '23 23:01

user1312242


1 Answers

I have just done this, I found you need to add the KnownTypesAttribute to the interface.

[ServiceContract]
[ServiceKnownType(typeof(MyContract1)]
[ServiceKnownType(typeof(MyContract2)]
[ServiceKnownType(typeof(MyContract3)]
public interface IMyService
{
    [OperationContract]
    object TakeMessage();

    [OperationContract]
    void AddMessage(object contract);

}

in you implementation, you will need to check the type to ensure it is one of your DataContracts.

EDIT

If you have a lot of contracts, you can use reflection to add them to the KnownTypes.

internal static class KnownTypeHelper
{
    public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider = null)
    {
        var types = Assembly.GetExecutingAssembly().GetTypes().Where(a => a.Namespace == "Company.Path.To.DataContractsNamespace").ToArray();

        return types;
    }
}

Then you can declare your interface as,

[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(KnownTypeHelper))]
public interface IMyService
{
    [OperationContract]
    object TakeMessage( );

    [OperationContract]
    void AddMessage(object contract);
}

This is a much cleaner way of doing it.

like image 109
TheRealTy Avatar answered Jan 28 '23 13:01

TheRealTy