REST service returns bad gateway when file is big and processing takes too long - rest

I have made a REST service that receives a ZIP-file, process and check some stuff, and returns an ID. This works fine for smaller ZIP-files, but when sending larger files (currently testing with 17 Mb), and the processing takes longer, the service returns "502 Bad gateway - Web server received an invalid response while acting as a gateway or proxy server".
I have tried to change all the variables I could find in the web config:
<binding name="webHttpTransportSecurity" maxReceivedMessageSize="163840000" maxBufferSize="163840000" closeTimeout="04:00:00" openTimeout="04:00:00" receiveTimeout="04:00:00" sendTimeout="04:00:00">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483648" />
<httpRuntime maxRequestLength="2147483647" enable="true" requestLengthDiskThreshold="10240" useFullyQualifiedRedirectUrl="true" executionTimeout="1000" appRequestQueueLimit="4000000" />
<serviceBehaviors>
<behavior>
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</serviceBehaviors>
Anyone have any idea how to make this work with bigger files? Where is this restriction, in IIS or something?
UPDATE: my code on server continue to run in the background and receives the whole file even though the caller of the service gets 'bad gateway'. So this is a 'false' 502.

Related

Self Hosted (console) WCF configuration

i had a WCF server running through a Console application, it will run as an azure service so i don't to host it in ISS.
I belived it work well and share datas to my web app through ajax request. But when i maked a service that recieve a filestream, i realized that my binding configuration is not used at all. My WCF work same without binding section.
My probleme concerne especially the key "maxReceivedMessageSize" because default value limit me to 8Ko request and it is a problem for uploading file.
Bindings section (that i can comment) :
<webHttpBinding>
<binding name="MyBindingConfig" crossDomainScriptAccessEnabled="true" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" transferMode="Buffered">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None" />
</binding>
</webHttpBinding>
Services section :
<service name="MyData.Service.MyDataServiceRestFull">
<endpoint binding="webHttpBinding"
contract="MyData.Service.IMyDataServiceRestFull" bindingName="MyBindingConfig" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:9997/MyDataServer"/>
</baseAddresses>
</host>
</service>
Note that i tryed with basicHttpBinding and i had same issue.
The problem is that you're incorrectly referring to your binding in your <endpoint/> element. You're using the bindingName attribute, when you should be using the bindingConfiguration attribute:
<endpoint binding="webHttpBinding"
contract="MyData.Service.IMyDataServiceRestFull"
bindingConfiguration="MyBindingConfig" />

MaxReceivedMessageSize property not registering

I am receiving the following error when running my site:
System.ServiceModel.QuotaExceededException: The maximum message size quota for incoming messages (50000000) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.
So I increased this property in my client and server web.config files.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding maxReceivedMessageSize="250000000"></binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
As you see I increased it to "250000000". However, when running I still get the exact same message saying that the message size is only "50000000". Is there something else I am missing to change the size of the maxReceivedMessageSize property?
You are not targeting the correct binding. You should be mentioning it by name.
Example of this:
<basicHttpBinding>
<binding name="Binding1" maxReceivedMessageSize = "1000000">
<security mode="None" />
</binding>
</basicHttpBinding>
Details here.

WF Workflow Service Error Cannot obtain Metadata from http://localhost/OrderService/Service1.xamlx

I have created a Workflow service using Microsoft WF (https://msdn.microsoft.com/en-us/library/ff432975%28v=vs.110%29.aspx)
When i run the service in visual studio I'm getting the below error
Error: Cannot obtain Metadata from http://localhost/OrderService/Service1.xamlx
If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address.
For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange Error URI: http://localhost/OrderService/Service1.xamlx
Metadata contains a reference that cannot be resolved: 'http://localhost/OrderService/Service1.xamlx'.
The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.HTTP GET Error URI: http://localhost/OrderService/Service1.xamlx
There was an error downloading 'http://localhost/OrderService/Service1.xamlx'. The request failed with an empty response.
My config is below. I have added the Meta Exchange lines in the config file also.
<system.serviceModel>
<services>
<service behaviorConfiguration="metadataBehavior" name="MyService">
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="metadataBehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
<!--Connection String for the WF SQL Presistance-->
<sqlWorkflowInstanceStore connectionString="Data Source=AAAAA;Initial Catalog=KK_SQLPersistenceStore;Asynchronous Processing=True" instanceEncodingOption="None" instanceCompletionAction="DeleteAll" instanceLockedExceptionAction="BasicRetry" hostLockRenewalPeriod="00:00:30" runnableInstancesDetectionPeriod="00:00:02" />
<workflowIdle timeToUnload="0"/>
</behavior>
</serviceBehaviors>
</behaviors>
Try changing you endpoint address to this
<endpoint address="http://localhost/OrderService/Service1.xamlx/mex" binding="mexHttpBinding" contract="IMetadataExchange" />

Securing WCF REST service for use with iPhone application

I've a created a simple WCF REST service which I intend to consume from an iPhone application.
The service works fine but now I'd like to secure it.
In my test enviornment (IIS on Windows 7) I already setup a self signed certificate using makecert.exe.
I also overridden the validate() method so I can use a custom username & password (since windows authentication is out of the question).
Now I'm stuck for more than two days figuring out how to configure everything so it can work.
My goal now is to be able to do a simple GET request via the browser, something like:
https://localhost/testservice/service1.svc/sayHello
When this will work I'll continue on to all iPhone related stuff.
Any help / examples will be highly appreciated!
Here's my web.config:
<system.serviceModel>
<services>
<service name="IphoneWcf.Service1" behaviorConfiguration="IphoneWcf.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="webBinding" behaviorConfiguration="webBehavior" contract="IphoneWcf.IService1">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<!--<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> -->
<host>
<baseAddresses>
<add baseAddress="https://localhost/iphonewcf" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="webBehavior">
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="IphoneWcf.Service1Behavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpsGetEnabled="false" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="webBinding">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
Thanks in advance!
Another option would be to create another cert for client authentication. I'm pretty sure the iPhone supports X509 certs. Just change your config to have a client credential type of "Certificate". This works for basic authentication, but you may still need custom user/name pwd over Basic if you want to uniquely identify every client.
You shouldn't have to override any method. Just declare Digest transport security in your basicHttpBinding:
<bindings>
<basicHttpBinding>
<binding name="SecurityByTransport">
<security mode="Transport">
<transport clientCredentialType="Digest" />
</security>
</binding>
</basicHttpBinding>
</bindings>
In you iPhone app you handle the NSURLConnectionDelegate connection:didReceiveAuthenticationChallenge message as shown in Handling Authentication Challenges:
-(void)connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge previousFailureCount] == 0) {
NSURLCredential *newCredential;
newCredential=[NSURLCredential credentialWithUser:[self preferencesName]
password:[self preferencesPassword]
persistence:NSURLCredentialPersistenceNone];
[[challenge sender] useCredential:newCredential
forAuthenticationChallenge:challenge];
} else {
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}

Unable to set maxReceivedMessageSize through web.config

I have now investigated the 400 - BadRequest code for the last two hours.
A lot of sugestions goes towards ensuring the bindingConfiguration attribute is set correctly, and in my case, it is.
Now, I need YOUR help before destroying the building i am in :-)
I run a WCF RestFull service (very lightweight, using this resource for inspiration: http://msdn.microsoft.com/en-us/magazine/dd315413.aspx) which (for now) accepts an XmlElement (POX) provided through the POST verb.
I am currently ONLY using Fiddler's request builder before implementing a true client (as this is mixed environments).
When I do this for XML smaller than 65K, it works fine - larger, it throws this exception:
The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.
Here is my web.config file (which I even included the client-tag for (desperate times!)):
<system.web>
<httpRuntime maxRequestLength="1500000" executionTimeout="180"/>
</system.web>
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
</diagnostics>
<bindings>
<webHttpBinding>
<binding name="WebHttpBinding" maxReceivedMessageSize="1500000" maxBufferPoolSize="1500000" maxBufferSize="1500000" closeTimeout="00:03:00" openTimeout="00:03:00" receiveTimeout="00:10:00" sendTimeout="00:03:00">
<readerQuotas maxStringContentLength="1500000" maxArrayLength="1500000" maxBytesPerRead="1500000" />
<security mode="None"/>
</binding>
</webHttpBinding>
</bindings>
<client>
<endpoint address="" binding="webHttpBinding" bindingConfiguration="WebHttpBinding" contract="Commerce.ICatalogue"/>
</client>
<services>
<service behaviorConfiguration="ServiceBehavior" name="Catalogue">
<endpoint address=""
behaviorConfiguration="RestFull"
binding="webHttpBinding"
bindingConfiguration="WebHttpBinding"
contract="Commerce.ICatalogue" />
<!-- endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" / -->
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="RestFull">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Thanks in advance for any help leading to succesfull call with >65K XML ;-)
All right, this one really caused me a hard time resolving, which I will spare others for.
The challenge was in the fact, that I used the <%# ServiceHost Factory="System.ServiceModel.Activation.WebServiceHostFactory" Service="fullyQualifiedClassName" %>, which is a nice and easy factory implementation approach.
However, this approach has it drawbacks; since no configuration is needed in the web.config file, the WebServiceHostFactory class by design does not ever read from the web.config file.
I know; I could inherit from this class, and make the appropriate changes so it may indeed read from the config file, but this seemed a little out of scope.
My solution was to go back to the more traditional way of implementing the WCF; <%# ServiceHost Service="fullyQualifiedClassName" CodeBehind="~/App_Code/Catalogue.cs" %>, and then use my already configured values in the web.config file.
Here is my modified web.config file (with respect to Maddox headache):
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="XmlMessageBinding" maxReceivedMessageSize="5000000" maxBufferPoolSize="5000000" maxBufferSize="5000000" closeTimeout="00:03:00" openTimeout="00:03:00" receiveTimeout="00:10:00" sendTimeout="00:03:00">
<readerQuotas maxStringContentLength="5000000" maxArrayLength="5000000" maxBytesPerRead="5000000" />
<security mode="None"/>
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="fullyQualifiedClassName" behaviorConfiguration="DevelopmentBehavior">
<endpoint name="REST" address="" binding="webHttpBinding" contract="fullyQualifiedInterfaceName" behaviorConfiguration="RestEndpointBehavior" bindingConfiguration="XmlMessageBinding" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="RestEndpointBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="DevelopmentBehavior">
<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
<behavior name="ProductionBehavior">
<serviceDebug httpHelpPageEnabled="false" includeExceptionDetailInFaults="false"/>
<serviceMetadata httpGetEnabled="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Another benefit of this change is, that you can now reference your WCF-rest service directly from .NET; this cannot be done using the Factory model and my implementation of XmlElement through out the solution.
I hope this can help others with similar issues ...
I know this is a very old Question and it already has an answer...
Anyway...
What I did to solve this "issue" I created a Factory inherited from WebServiceHostFactory and created a Custom Service Host inherited from WebServiceHost
And in the host I overrode the OnOpening method like this
protected override void OnOpening()
{
base.OnOpening();
foreach (var endpoint in Description.Endpoints)
{
var binding = endpoint.Binding as System.ServiceModel.Channels.CustomBinding;
foreach (var element in binding.Elements)
{
var httpElement = element as System.ServiceModel.Channels.HttpTransportBindingElement;
if (httpElement != null)
{
httpElement.MaxBufferSize = 2147483647;
httpElement.MaxReceivedMessageSize = 2147483647;
}
}
}
}
I think i had the same issue, but when i configured the default-binding for webHttp then it worked:
<bindings>
<webHttpBinding>
<binding maxReceivedMessageSize="2000000"
maxBufferSize="2000000">
<readerQuotas maxStringContentLength="2000000"/>
</binding>
</webHttpBinding>
</bindings>
Observe: no name on the binding.
This is a blog entry I wrote that reproduces this problem with an absolutely minimal WCF server and client piece:
WCF - Fixing client side string length exceptions
In particular, you may need a Custom Binding Configuration. At least reproducing this sample may give you some ideas for your particular situation.