Reputation: 2431
I am making a custom WCF client which I want to register the classes dynamically at application startup.
I am using the attribute ServiceKnownType
on the client interface:
[ServiceContract(Namespace = "http://example.com/schema/commandservice/v1.0", ConfigurationName = "WcfProxies.IVotesCommandService")]
[ServiceKnownType("GetKnownTypes")]
public interface IVotesCommandService
{
[OperationContract(Action = "http://example.com/schema/commandservice/v1.0/VotesCommandService/Execute", ReplyAction = "http://example.com/schema/commandservice/v1.0/VotesCommandService/ExecuteResponse")]
void Execute(object command);
[OperationContract(Action = "http://example.com/schema/commandservice/v1.0/VotesCommandService/Execute", ReplyAction = "http://example.com/schema/commandservice/v1.0/VotesCommandService/ExecuteResponse")]
Task ExecuteAsync(object command);
}
}
public class VotesCommandServiceClient : ClientBase<IVotesCommandService>, IVotesCommandService
{
public VotesCommandServiceClient()
{
}
public VotesCommandServiceClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public VotesCommandServiceClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public VotesCommandServiceClient(string endpointConfigurationName, EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public VotesCommandServiceClient(Binding binding, EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public void Execute(object command)
{
Channel.Execute(command);
}
public Task ExecuteAsync(object command)
{
return Channel.ExecuteAsync(command);
}
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
var types = new[]
{
typeof (UserVotedOnTopicCommand)
};
return types;
// collect and pass back the list of known types
}
}
But when I try and use the class it throws an exception:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll. Additional information: ServiceKnownTypeAttribute in MyApp.Votes.WinSvc.Test.WcfProxies.IVotesCommandService refers to a method GetKnownTypes that does not exist in type MyApp.Votes.WinSvc.Test.WcfProxies.IVotesCommandService
But if i declare an externally typed resolver below:
[ServiceKnownType("GetKnownTypes", typeof(Helper))]
public interface IVotesCommandService
.... snip...
static class Helper
{
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
var types = new[]
{
typeof (UserVotedOnTopicCommand)
};
return types;
}
}
Then it works?!
I have also tried setting ServiceKnownType
on the proxy class implementation as below:
[ServiceKnownType("GetKnownTypes")]
public class VotesCommandServiceClient : ClientBase<IVotesCommandService>, IVotesCommandService
{
... snip ...
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
var types = new[]
{
typeof (UserVotedOnTopicCommand)
};
return types;
}
}
But then the actual GetKnownTypes
function is never called and the proxy bombs out when trying to use it as it doesn't know the contract being sent.
What am I doing wrong please and why isn't the static GetKnownTypes function inside the class being called?
Upvotes: 1
Views: 878
Reputation: 39085
MSDN documentation for the constructor overload you're using says:
Use this constructor when applying the ServiceKnownTypeAttribute to a class that contains methods that return known types.
It is looking for "GetMethodNames" on the type that the attribute is defined (IVotesCommandService
), not on the run-time type (VotesCommandServiceClient
).
You would need to define as [ServiceKnownType("GetKnownTypes", typeof(VotesCommandServiceClient)]
.
Upvotes: 2