1
votes

I created a WCF service for logging exceptions (I realize if the network is down, things won't be logged...there are fallbacks in place)

Anyhow, it has two methods

int LogException(MethodBase methodBase, Exception exception)
int LogMessage(MethodBase methodBase, string message, string data)

When I try and add the service to a new project, the .cs file is not created. I ran svcutil, and copied the .cs and config settings into the project, and tried calling the service with the generated client. I got the following two error

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

With inner exception

Type 'System.Reflection.RuntimeMethodInfo' with data contract name 'RuntimeMethodInfo:http://schemas.datacontract.org/2004/07/System.Reflection' 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.

What do I need to do to make this work?

1

1 Answers

5
votes

When communicating via WCF, WCF needs to know precisely what will be sent across the boundary. So taking an "Exception" is fine and all, but almost always, you'll be passing subtypes of exception, so you need to tell the contract which types of Exceptions will be passed across the boundary. The same thing goes for MethodBase. You probably want to tell it that you'll actually be passing a MethodInfo some of the time.

Because these aren't your types, you probably can't use the KnownType attribute (the attribute usually gets placed on the base class or interface). In this case, you need to use a Data Contract Resolver. It tells the serialization / deserialization engine how to find the sub types.

http://msdn.microsoft.com/en-us/library/ee358759.aspx

Although you can use the ServiceKnownType attribute. Your contract should look something like this:

[DataContract]
public interface ILoggingStuff // choose a better name than this
{
    [OperationContract]
    [ServiceKnownType(typeof(MethodInfo))]
    int LogException(MethodBase methodBase, Exception exception);
    [OperationContract]
    [ServiceKnownType(typeof(MethodInfo))]
    int LogMessage(MethodBase methodBase, string message, string data);
}

This tells WCF that MethodBase could be using the descending Type MethodInfo.