4

I have a WCF Service that based on Writing Highly Maintainable WCF Services. Requests are processed using a CommandService:

[WcfDispatchBehaviour]
[ServiceContract(Namespace="http://somewhere.co.nz/NapaWcfService/2013/11")]
[ServiceKnownType("GetKnownTypes")]
public class CommandService
{
    [OperationContract]
    public object Execute(dynamic command)
    {
        Type commandHandlerType = typeof(ICommandHandler<>).MakeGenericType(command.GetType());
        dynamic commandHandler = BootStrapper.GetInstance(commandHandlerType);
        commandHandler.Handle(command);
        return command;
    }

    public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
    {
        var coreAssembly = typeof(ICommandHandler<>).Assembly;
        var commandTypes =
            from type in coreAssembly.GetExportedTypes()
            where type.Name.EndsWith("Command")
            select type;

        return commandTypes.ToArray();
    }
}

Everything works great (thanks Steve) but now I need to add the ability to upload a file to the service. From what I've read and based on errors received during testing, WCF needs to use a [MessageContract] when uploading a file using a Stream. So I've decorated my command class and put the non-Stream members into the message header, and updated my binding definition to use streaming:

[MessageContract]
public class AddScadaTileCommand
{
    [MessageHeader(MustUnderstand = true)]
    public int JobId { get; set; }

    [MessageHeader(MustUnderstand = true)]
    public string MimeType { get; set; }

    [MessageHeader(MustUnderstand = true)]
    public string Name { get; set; }

    [MessageBodyMember(Order = 1)]
    public Stream Content { get; set; }
}

Unfortunately when I call the service with a file to upload I get an error:

There was an error while trying to serialize parameter http://somewhere.co.nz/NapaWcfService/2013/11:command. The InnerException message was 'Type 'System.IO.FileStream' with data contract name 'FileStream:http://schemas.datacontract.org/2004/07/System.IO' is not expected.

So I added a new method to the service specifically for the file upload request:

[OperationContract]
public void Upload(AddScadaTileCommand addScadaTileCommand)
{
    Type commandHandlerType = typeof(ICommandHandler<>).MakeGenericType(typeof(AddScadaTileCommand));
    dynamic commandHandler = BootStrapper.GetInstance(commandHandlerType);
    commandHandler.Handle(addScadaTileCommand);
}

This works perfectly, unless I change the AddScadaTileCommand parameter to dynamic in the method definition, in which case I get the same error as above. This appears to indicate that the [MessageContract] attributes are not applied or ignored when using dynamic as the type of the parameter. Is there any way to resolve this or will I need to create separate methods for requests that involve streams?

Steven
  • 166,672
  • 24
  • 332
  • 435
David Clarke
  • 12,888
  • 9
  • 86
  • 116

0 Answers0