0

I have WCF RESTful service and Android client.

Server replies with 400 when I do bigger request. It seems that I have 65k limit issue like in here or in other million posts on same problem.

However, I can't seem to be able to fix it. Here is how my web.config looks

    <system.serviceModel>
    <diagnostics>
      <messageLogging logMalformedMessages="true" logMessagesAtServiceLevel="true"
        logMessagesAtTransportLevel="true" />
    </diagnostics>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint name="myEndpoint" helpEnabled="true" automaticFormatSelectionEnabled="true" maxReceivedMessageSize="1000000" />
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>

Here is code example of service function:

[WebInvoke(UriTemplate = "/trips/{TripId}/inspection", Method = "POST")]
        [Description("Used on mobile devices to submit inspections to server")]
        public void PostTripInspection(string tripId, Inspection inspection)
        {
            return;
        }

Here is code inside my Web project which hosts WCF (Global.asax.cs)

private static void RegisterRoutes()
        {
            // Setup URL's for each customer
            using (var cmc = new CoreModelContext())
            {
                foreach (var account in cmc.Accounts.Where(aa => aa.IsActive).ToList())
                {
                    RouteTable.Routes.Add(
                        new ServiceRoute(
                            account.AccountId + "/mobile", new WebServiceHostFactory(), typeof(MobileService)));
                }
            }
        }

From what I understand Java HttpClient doesn't impose any limits so it's on WCF side. Any pointers on how to solve this issue or how to intercept message in WCF?

EDIT 2: This is what trace shows. And when I modigy standardEndpoint it doesn't help...

enter image description here

Community
  • 1
  • 1
katit
  • 17,375
  • 35
  • 128
  • 256

2 Answers2

1

Forgive me if you've seen this link (Similar StackOverflow Question):

By default the WCF Transport is limited to sending messages at 65K. If you want to send larger you need to enable Streaming Transfer Mode and you need to increase the size of MaxReceivedMessageSize, which is there just as a guard to prevent someone killing your server by uploading a massive file.

So, you can do this using binding configuration or you can do it in code. Here is one way to do it in code:

var endpoint = ((HttpEndpoint)host.Description.Endpoints[0]); //Assuming one endpoint
endpoint.TransferMode = TransferMode.Streamed;
endpoint.MaxReceivedMessageSize = 1024 * 1024 * 10;  // Allow files up to 10MB
Community
  • 1
  • 1
jglouie
  • 12,523
  • 6
  • 48
  • 65
  • For programmatic setting, see http://social.technet.microsoft.com/wiki/contents/articles/streaming-large-data-files-using-webhttpbinding-wcf.aspx. Or, via web.config, try adding transferMode="Streamed" to the binding element. – jglouie Jul 06 '11 at 16:09
  • This link doesn't show where endpoint get's configured. But anyway, I think this is not right direction. My Android client does plain POST, there is no streaming involved. It just POSTs big json string.. – katit Jul 06 '11 at 16:14
  • The binding for the endpoint is configured in the Test() method of that link. – jglouie Jul 06 '11 at 16:18
  • I see. But it's showing how SERVER streams data back to client. Like I mentioned, in my case server does not reply to client with data. Client posts big json to server. So, I need to configure server so it listens and doesn't reject – katit Jul 06 '11 at 16:21
  • @katit That code was only relevant to people using the new WCF Web API library from http://wcf.codeplex.com – Darrel Miller Jul 06 '11 at 16:26
  • It demonstrates both directions. UploadFile involves the Client performing a large HTTP POST to the Server. Follow the UploadFile logic in the example – jglouie Jul 06 '11 at 16:28
  • I edited my original post to show you all the code I have. I think I should be able to do what I need via web.config but seems like nothing works. – katit Jul 06 '11 at 16:43
0

You don't need to use streaming in this case - all you need to do is to increase the maxReceivedMessageSize quota on the standard webHttpEndpoint:

<standardEndpoints>
  <webHttpEndpoint>
    <!-- 
        Configure the WCF REST service base address via the global.asax.cs file and the default endpoint 
        via the attributes on the <standardEndpoint> element below
    -->
    <standardEndpoint name=""
                      helpEnabled="true"
                      automaticFormatSelectionEnabled="true"
                      maxReceivedMessageSize="1000000"/>
  </webHttpEndpoint>
</standardEndpoints>

Update: if the config change didn't work (I don't know why), you can try increasing it in code. By using a custom service host factory, you get a reference to the endpoint object and you can increase the quota there. The code below shows one such a factory (you'll need to update the RegisterRoute code to use this new factory):

public class MyWebServiceHostFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        return base.CreateServiceHost(serviceType, baseAddresses);
    }

    class MyWebServiceHost : WebServiceHost
    {
        public MyWebServiceHost(Type serviceType, Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
        }
        protected override void OnOpening()
        {
            base.OnOpening();
            foreach (ServiceEndpoint endpoint in this.Description.Endpoints)
            {
                if (!endpoint.IsSystemEndpoint)
                {
                    Binding binding = endpoint.Binding;
                    if (binding is WebHttpBinding)
                    {
                        ((WebHttpBinding)binding).MaxReceivedMessageSize = 1000000;
                    }
                    else
                    {
                        CustomBinding custom = binding as CustomBinding;
                        if (custom == null)
                        {
                            custom = new CustomBinding(binding);
                        }

                        custom.Elements.Find<HttpTransportBindingElement>().MaxReceivedMessageSize = 1000000;
                    }
                }
            }
        }
    }
}
carlosfigueira
  • 85,035
  • 14
  • 131
  • 171
  • Thats what is seems, right? Makes sense to me but doesn't work :( See updated main post. I ran trace and YES, this property seem to be the problem. I wonder what binding I need to modify.. – katit Jul 06 '11 at 18:15
  • It should work, but if it doesn't, you can try the update solution I added to the answer. – carlosfigueira Jul 06 '11 at 18:55
  • I will mark your post as Answer since you pointed me back to where I should look. Guess WHAT?! It started to work after I removed "name = "" " from endpoint. Microsoft service configuration editor complained about it but code wouldn't register this config with any name. Tag has to be out... – katit Jul 06 '11 at 18:57