ReadResponse() failed: When uploading large amounts of data - c#

I came across an issue today when adding an upload data modification to a ASP.NET 3.5 C# Web App. The user needs to upload a spreadsheet with a .xls extension containing large amounts of data. That spreadsheet will be converted to a datatable and then inserted into SQL Via a SqlBulkInsert method. The problem I am having is the sheet I am currently working with has 16 columns and can only contain 24889 rows before I receive this message from the server via Fiddler, 'ReadResponse() failed: The server did not return a response for this request.' I've searched and not found much info on this related to my issue. Any help would be appreciated.

Try giving some values for maxRequestLength like below
<system.web>
<!-- ... -->
<httpRuntime maxRequestLength="204800"/>
<!-- ... -->
</system.web>

By default you can upload a file upto 4MB.
The size of your excel must be excedding the limit.
What you can do is set the setting in Web Configuration file
What this will do is increase the request size that server can respond to.

You need to look into server logs to figure out what cases it (or simply debug the server portion if you can). You also should see if it cased by simply size of the file or data in the file (if you do any processing).
Possible reasons:
you code gets the data, but fails in some way likely tearing down whole process
ASP.Net blocks request due to size (see Pankaj Garg answer).
your code is just too slow

Related

ASP.NET throwing 404 for large file and 400 for extremely large files

Currently writing an API that accepts files using multipart/form-data. Below are my settings in Web.config. IIS is set to 1.0737GB limit and .NET is set to a 1.0485GB limit.
<httpRuntime requestValidationMode="2.0" maxRequestLength="1048576" executionTimeout="1000000" targetFramework="4.7.1" />
<requestFiltering>
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
When I upload a file around 1.5-2GB in size I get a 404 back as described in the Microsoft documentation linked below. This is my expected response from the server. But, when I upload a much larger file, around 2.5GB+, I get a 400 Bad Request instead. I have been looking around for documentation to describe why this would happen and why I would not expect to always see a 404 instead, but have found nothing stating a 400 could be returned. The only difference between the requests is the files attached, nothing else is changed. To make the larger file size I also just zipped two of the original file that throws the 404 together. As additional details, the endpoint is covered in Unit and Integration tests that verify normal use case functionality. The endpoint works when manually tested with files below the IIS/.NET set limits. This behavior has also been seen when manually tested with a C# library project as well as Postman. Any help is greatly appreciated, thanks in advance!
https://learn.microsoft.com/en-us/iis/configuration/system.webserver/security/requestfiltering/
Clarification on my use case:
A clarification is that I'm not trying to increase the size limit of my requests, I just need to make sure anything over the size limit returns the same error. The documentation that will be publicly available needs to state the return value in case of error and currently it can be either a 404 or a 400 and I can't explain explicitly why in the documentation yet.
Thanks to help from all of the commenters, the following link provided by Brian Clink answered the question. https://sitecore.stackexchange.com/questions/11788/sitecore-media-file-upload-above-2gb-throws-bad-request-400
IIS forces the max size to be 2GB. So, for all requests less than 2GB that are larger than your custom IIS settings a 404.13 is returned. For all requests over 2GB a 404 is returned.

Is it possible to access parameters sent via multipart/form-data without waiting for the entire form to arrive

I have a pretty big video file I upload to a web service via multipart/form-data.
It takes ~ 30 seconds to arrive and I would prefer not waiting that long simply to access parameters I send along with the file.
My question is simple, can I access parameters sent with the form without waiting for the video payload to be uploaded?
Can this be done using headers or any other methods? 
Streaming vs. Buffering
It's about how the webserver is set up. For IIS you can enable Streaming.
Otherwise, by default, IIS will use 'buffering' - the whole request is loaded into memory first (IIS's memory that you can't get to) before your app running in IIS can get it.
Not using IIS? You have to figure out how to get the webserver to do the same thing.
How to stream using IIS:
Streaming large file uploads to ASP.NET MVC
Note the way the file is read in the inner loop:
while ((cbRead = clientRequest.InputStream.Read(rgbBody, 0, rgbBody.Length)) > 0)
{
fileStream.Write(rgbBody, 0, cbRead);
}
Here instead of just saving the data like that question does, you will have to parse any xml/json/etc or whatever contains the file parameters you speak of ... and expect the video to be sent afterwards. You can process them right away if it's a quick process ... then get the rest of the video ... or you can send them to a background thread.
You probably won't be able to parse it just dumping what you have to a json or xml parser, there will be an unclosed tag or } at the top that isn't closed til after the video data is uploaded (however that is done). Or if it's multipart data from a form submission, as you imply, you will have to parse that partial upload yourself, instead of just asking IIS for the post data.
So this will be tricky, you can first start by writing 1k at a time to a log file with a time stamp to prove that you're getting the data as it comes. after that it's just a coding headache.
Getting this to work also means you'll have to have some control over the client and how it sends the data.
That's because you'll at least have to ensure it sends the file parameters FIRST!
Which concerns me, because, if you have control of the client, why can't you take the simple route (as Nobody and Nkosi imply) and use 2 requests? You mention you need one. Why not write js client code to send the parameters first in an XHR and then the file in a second request, using a correlation ID in both to tie them together? (the server could return this from the first request and you could send it in the 2nd).
Obviously, if you're just having a form with some inputs and a file upload and doing submit, then you need one request ;-) But if you have control over the client side you're not stuck with that.
Good luck, there is some advanced programming here, but nothing super high-tech. You will make it work!!!
If you don't have control over the server code, you are probably stuck, if the server app's webserver is buffering, the server app won't get anything, of course, if you wanted to do something with the file parameters first, this really implies you have control of the server side ;-)

Find out the max file upload size allowed on server

I have an image upload tool and I want to report an error before the file is uploaded if the size is too large for my server.
Is there a c# ASP .NET MVC 5 command for finding out this size?
I don't know if it makes a difference but i'm hosted with Microsoft Azure.
You server application can to know this value, by reading Web.config:
var section = ConfigurationManager.GetSection("system.web/httpRuntime") as HttpRuntimeSection;
// Value in KBs. 4096 means 4Mb.
var maxRequestLength = section.MaxRequestLength;
You'd have to write a controller action that queried the IIS configuration and returned the value to the client.
The client would need to call this method to find out the limit before attempting the upload.
A way to find out the value is described here:
How to read maxAllowedContentLength

.NET WebService Timeout Exception

I am getting the following exception when calling a web service operation in my .NET application:
System.Net.WebException: The operation has timed out at
System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest
request) at
System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse(WebRequest
request) at
System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String
methodName, Object[] parameters) at
org.wvi.hrmgmt.HRManagementServiceserviceagent.LoadReducedTemplate(LoadReducedTemplateRequest
LoadReducedTemplateRequest) at
org.wvi.mgmt.hr._ServiceClient.UploadReducedTemplate()
Basically, a user uploads a file into the web server and the binary contents of this file is being passed as one of the input parameters when calling a web service operation. The size of the file is 1,397 KB and if I choose to process this file, I am getting the exception. Whereas, processing a file with a relatively smaller size, supposed 127 KB, gives a successful response.
I have done the below steps in order to solve the dillema:
Setting the web service timeout to infinite. -> Not getting an exception and any response
Adding Response.Close() -> Not getting any response
Editing the web.config in the IIS server and adding the following lines: -> Still getting the exception
<system.web>
<customErrors mode="Off"/>
<httpRuntime executionTimeout="600" maxRequestLength="16384"/>
<sessionState timeout="540"/>
</system.web>
However, to no avail, I'm still getting the above exception. I am using a Javascript plugin called AjaxUpload from GitHub and I can't figure out whether they have file upload size limit. Besides, I have checked the file if it is being uploaded on the server and it does, therefore, the issue may not be because of that plugin.
Another issue is that I am getting the same exception when uploading the file after a period of time the web page has been opened. I surmise that this has something to do with session timeout so I added an additional line in my web.config file specifying the maximum timeout. Please advise me if I'm on the right track.
Are there additional settings I need to apply in my IIS server to make the operation successful? Otherwise, are there anything I am missing? If you have experienced this before, kindly inform me what to do.
Thank you so much,
Ralph
This might be due to lot of proxy opened before. So I suggest you to delete Service.Reference.Config along with web service reference and add the service reference again and see whether it solves your problem.
Adding on to the previous answer, you may try setting up the execution time out on the proxy class , Refer this discussion
And you service call is performing a long running task you may prefer to have a lengthy time out for any webservice call by setting the timeout in proxy class as said before.

How can you configure or extend BITS (Background Intelligent Transfer Service) to read files from a Sql Server Database

I have a ASP .NET load balanced application (webservice and website). It runs on SQL server. I need to be able to provide large files for download. However, because of the load balancing situation, the files are stored in the SQL database as opposed to the file system. BITS seems to be the best approach. I have full control of the client. However, i don't know how to configure BITS to read the file from the database. I know how to write the C# code for that, but i don't know how to get BITS to hook into it as opposed to reading the file from the file system.
Any ideas?
You can create a custom http handler by implementing System.Web.IHttpHandler. The ProcessRequest(HttpContext context) method is where you will write your file retrieval code from the database. Since BITS operates with range requests you will need to parse the value of context.Request.Headers["Range"] to get the start and end bytes requested. In the ProcessRequest you can read the binary from the database using the SqlCommand.ExecuteReader(CommandBehavior.SequentialAccess) method and set the resulting binary in context.Response.OutputStream. Remember to call context.Response.Flush() at the end.
The custom HttpHandler will serve a particular file extension (e.g. '.file'). This is what needs to be done in IIS:
Both IIS Versions
Add to section in in web.config:
IIS 6.0
Add .file (application/x-zip-compressed) extension as MIME type for the website.
Add Application Extension (Website Properties  Virtual Directory  Configuration  Mappings)
Extension: .file
Executable Path(s): %windir%\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll
%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll
IIS 7.0
Add to section in in web.config:
Add to section in in web.config:
<mimeMap fileExtension=".file" mimeType="application/x-zip-compressed" />
Hope that's enough to get you started.
Have a look at 2008 Books Online OpenSqlFilestream. That API has examples that may help you.

Categories