WCF 3.5 Issue (CustomBinding assigned instead of WebHttpBinding when a parameter is a Stream)

476 views Asked by At

In my service contract I am exposing a method that takes Stream as a parameter:

[OperationContract]
[WebInvoke(UriTemplate = "/Upload?fileName={fileName}", Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
Stream Upload(String fileName, Stream fileData);

when I do this my custom WebServiceHost implementation (which is instantiated from a custom WebServiceHostFactory implementation) is seeing the endpoint binding as being CustomBinding and not WebHttpBinding:

public class myWebServiceHost : WebServiceHost {
  .
  .
  .
  protected override void OnOpening() {
    base.OnOpening();
    if (base.Description != null) {
      foreach (ServiceEndpoint endpoint in base.Description.Endpoints) {
        WebHttpBinding binding = endpoint.Binding as WebHttpBinding;
        if (binding != null) { //Will always be null given the operation contract above
          Int32 MB = 1048576 * Convert.ToInt32(ConfigurationManager.AppSettings["requestSizeMax"]);
          binding.MaxReceivedMessageSize = MB;
          binding.TransferMode = TransferMode.Streamed;
        }
      }
    }
  }
}

This is an issue because I need to upload files larger than 64KB... any ideas on how I would go about setting MaxReceivedMessageSize for a CustomBinding or how to insure my Binding gets set to a WebHttpBinding.

P.S. I need to do this programmatically, so .config settings won't be of any use to me.

1

There are 1 answers

0
Xorcist On BEST ANSWER

Okay so after digging long and hard on this one, this is what I came up with:

protected override void OnOpening() {
  base.OnOpening();
  if (base.Description != null) {
    foreach (ServiceEndpoint endpoint in base.Description.Endpoints) {
      Int32 MB = 1048576 * Convert.ToInt32(ConfigurationManager.AppSettings["requestSizeMax"]);
      switch(endpoint.Binding.GetType().ToString()) {
        case "System.ServiceModel.Channels.CustomBinding":
          CustomBinding custom = (CustomBinding)endpoint.Binding;
          custom.Elements.Find<HttpTransportBindingElement>().MaxReceivedMessageSize = MB;
          custom.Elements.Find<HttpTransportBindingElement>().TransferMode = TransferMode.Streamed;
        break;
        case "System.ServiceModel.WebHttpBinding":
          WebHttpBinding webhttp = (WebHttpBinding)endpoint.Binding;
          webhttp.MaxReceivedMessageSize = MB;
          webhttp.TransferMode = TransferMode.Streamed;
        break;
      }
    }
  }
}

It works, though it can definitely be improved upon. I still need to see if there is a more generic way of handling this, rather than separating the cases by type. Though at the moment I don't see any other way to do it (since the type of binding is based on methods in the service itself, remember it only switched from WebHttpBinding to CustomBinding when I added a Stream parameter to one of the service methods).

  • If anyone has any other insight on this topic, please post.