Jan-Erik
Jan-Erik

Reputation: 21

How do I consume an WCF service in Silverlight which uses the ProtoBuf-net serializer?

It's 2am, and I've been trying to figure out this the whole evening: How do I consume an WCF service in Silverlight which uses the ProtoBuf-net serializer?

Just to clarify one thing: The service(s) works great when calling them from my test console app.

The top level service is exposed by using the BasicHttpEndpoint (for compability), but I'm very open for other bindings if that solves my problem.

Anyway, in .NET (not Silverlight) I can consume the services as follows:

I have an generic method, GetService, which creates the service for me:

... Code removed ...
EndpointAddress endpointAddress = new EndpointAddress(address);
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential)
{
    MaxReceivedMessageSize = int.MaxValue,
    MaxBufferSize = int.MaxValue,
};
binding.ReaderQuotas.MaxArrayLength = int.MaxValue;

ContractDescription contract = ContractDescription.GetContract(typeof(TServiceType));
ServiceEndpoint serviceEndpoint = new ServiceEndpoint(contract, binding, new EndpointAddress(address));

factory = new ChannelFactory<TServiceType>(serviceEndpoint);
AddBehaviors(serviceEndpoint);

ClientCredentials defaultCredentials = factory.Endpoint.Behaviors.Find<ClientCredentials>();
factory.Endpoint.Behaviors.Remove(defaultCredentials);
factory.Endpoint.Behaviors.Add(credentials);
... Code removed ...

Then the AddBehavior method is extracted:

private static void AddBehaviors(ServiceEndpoint serviceEndpoint, int maxItemsInObjectGraph = int.MaxValue)
{
    foreach (OperationDescription operation in serviceEndpoint.Contract.Operations)
    {
        DataContractSerializerOperationBehavior operationBehavior = operation.Behaviors.Find<DataContractSerializerOperationBehavior>();
        if (operationBehavior != null)
        {
            operation.Behaviors.Remove(operationBehavior);
        }

        ProtoOperationBehavior protoOperationBehavior = operation.Behaviors.Find<ProtoOperationBehavior>();
        if (protoOperationBehavior == null)
        {
            protoOperationBehavior = new ProtoOperationBehavior(operation);
            operation.Behaviors.Add(protoOperationBehavior);
        }
        protoOperationBehavior.MaxItemsInObjectGraph = int.MaxValue;
    }
}

Unfortunately it's not possible to do this in Silverlight:( So I need some other way to achieve the same thing, and right now I'm stuck. Any suggestions is highly appreciated!

Upvotes: 2

Views: 446

Answers (2)

Marc Gravell
Marc Gravell

Reputation: 1063338

Yes, it is a pain. Carlos has an excellent answer on this, but a reduced option might be "transfer byte[] or Stream over the WCF boundary, and handle the serialize/deserialize manually". In most cases this is a single-line call to a Serializer.* method, so not overly tricky.

Upvotes: 0

carlosfigueira
carlosfigueira

Reputation: 87258

Silverlight doesn't have the DataContractSerializerOperationBehavior class (it's internal), so you can't use the "traditional" way of replacing the serializer. It's possible to do, but it requires a lot of steps. I published one way of doing it in the post at http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/24/wcf-extensibility-custom-serialization-in-silverlight.aspx.

Upvotes: 1

Related Questions