0
votes

I'm using JMeter 3.2 to test my site. I've used 2 prior versions, so I have some clue what I'm doing.

I'm testing an ASP.NET 4.5 site.

When I record a file upload I get a "fail" page back because my application is entering the "file uploaded" procedure, but the HttpPostedFileBase is null.

The HTTP Request has everything filled out as I would expect it to be.

Method: POST
Path: the /context/controller/action as expected
Redirect Automatically unchecked
Follow Redirects, Use KeepAlive, Use mutipart/form-data for POST, and Browser-compatible headers checked
The File Path has the filename (no path info) as expected
The Parameter Name is correct
The MIME Type is correct

If I disconnect the proxy and upload the file it works just fine.

If I stop recording, change the listener to Simple Controller, and playback the recorded session I can see that the "fail" page comes back. It is a response status 200 because it's a user friendly error page, but I added an Assertion Response to capture the failed status.

In the View Results Tree my request looks like this:

POST data:
--xr9jIAHNizYdrOAAzOIT6Yuvtp-zJlfaoDdNP
Content-Disposition: form-data; name="notInvolvedVariableName"

false
--xr9jIAHNizYdrOAAzOIT6Yuvtp-zJlfaoDdNP
Content-Disposition: form-data; name="fileUploadVariableName"; filename="JustFileName.txt"
Content-Type: text/plain

<actual file content, not shown here>
--xr9jIAHNizYdrOAAzOIT6Yuvtp-zJlfaoDdNP--

Cookie Data:
ASP.NET_SessionId=sessionIDblabla

Request Headers:
Connection: keep-alive
Referer: THIS_STILL_HAS_HTTPS_AND_EXTERNAL_SERVER_IP_FROM_WHEN_I_RECORDED_THE_UPLOAD/UploadFile
Accept-Language: en-US,en;q=0.5
DNT: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Upgrade-Insecure-Requests: 1
Accept-Encoding: gzip, deflate, br
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0
Content-Length: 9203
Content-Type: multipart/form-data; boundary=xr9jIAHNizYdrOAAzOIT6Yuvtp-zJlfaoDdNP; charset=UTF-8
Host: INTERNAL_IP

I was wondering if recording through HTTPS plays a role in the error.

I know that my FileServer Base is pointing to the right folder (through checking the jmeter.log file and I tested it by changing the name in my HTTP Request which gave me the "File Not Found" IOException).

I re-recorded the process using the internal path to see if that made a difference. It didn't. It still failed while recording. The playback request does show the referrer as HTTP internal IP now. But the playback still returns the fail page (a shocker since the fail page showed during recording).

I looked at multiple "how to upload a file in JMeter" pages and they all say exactly what I'm doing. Most pages never say what version they're referring to.

I set the Debug Level to Debug and played it back again. In the log file I see the headers and the file contents. It is in readable text, not base64 or zipped (but I think that's OK. In Fiddler the file content is readable as well). The filename is in the header as expected.

So it looks like the log is sending everything, but it's not making it to the server (during recording nor playback). So what's going on?

Edit:

From Fiddler in the Headers:

Manually (works) Content-Length: 9212 Connection: keep=alive

JMeter (doesn't work) Content-Length: 9188 Content-Type contains charset=US-ASCII Connection: keep=alive Connection: Keep-Alive

I'm not an expert, but I don't think the extra capitalized version of keep alive affects anything. I also doubt the charset sepcification affects anything.

The content in the TextView looks identical to me. The content in the Raw view has the headers in a different order, but they're all essentially the same (with the extra Keep Alive in JMeter).

Content Length doesn't include the header, but the body looks exactly the same other than boundry. The byte difference is coming from the difference in boundry length. It's 32 in JMeter and 40 manually. It's in the content 3 times, adding up to 24. That length changes each run, so I figure it shouldn't be the cause.

So I am thinking one of your links is certainly the cause because it looks like everything is sending correctly. I'm confused as to why it's received differently, but I'll read up and see where that gets me.

Edit 2:

I don't believe that it's a correlation issue.

My action declaration is sanitized as this:

[ValidateInput(false)]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UploadFile(HttpPostedFileBase myFile)
{
    logger.DebugFormat("Entered UploadFile with {0}", myFile != null ? myFile.FileName : "null filename");
    ...
}

The log entry is saying "Entered UploadFile with null filename".

On the regular GUI there's javascript that will prevent you from submitting without attaching a file. JMeter doesn't run js, but everything tells me that JMeter IS sending the file.

I added to the web.config, and that made no difference.

What else on IIS/ASP would be allowing the function call but blocking the file?

I have another file upload where the function takes no params and it reaches into the Request object.

if (null != Request.Files && Request.Files.Count > 0)
{
    HttpPostedFileBase hpf = Request.Files[0];
}//if
else
{
    logger.DebugFormat("Entered UploadFile with null filename or 0 files");
}

That one also fails to receive the file.

Edit 3:

I created a sample application where I am having this issue. It logs to C:\Logs.

NOTE: This link is superseded by a link below. http://s000.tinyupload.com/?file_id=49840904361057335433

Hit file upload in the bottom left. I included a log in the zip.

Just in case it was a FireFox issue I tried recording in IE and had the same problem. Edit 4:

I loaded the test app onto another web server (just to make sure it wasn't something the original server was blocking). I have the same results there.

To help others use the test app above:

So build the app attached above (Visual Sutio 2015).
Publish it (C:\Logs is where it will build). Zip Publish_WebApp1.
Deploy that to a web server (I'm using IIS 10 on the second server).
Try to record any file upload.
Check the log file.
Try uploading a file without the jmeter proxy (for comparison).

Edit 5: I ran Wireshark on the second server. I'm seeing a "Server 400 Bad Request: The request is badly formed" error. When I'm recording.

http://s000.tinyupload.com/?file_id=76890258829912351911

And then the packet showing the post looks like garbage (the highlighted post length 96). In the manual run I can see the text of the uploaded file (see the post with length 907). I can't upload this capture due to the nature of the file I uploaded, but I could repeat it with a sharable file if someone want to look at it.

Edit 6: I added detail to the "post-upload" page in the sample site.

I also made one big upload with the source code for the sample site, the compiled site, and a JMeter script.

Sample Site with Code

Visual Studio 2015: under projects I have the WebApplication1 source code zipped

Logs: I have a sample log file with notes on wha tthe results look like. I have the zipped IIS-ready compiled web site. (unzip it into inetpub and promote the folder to an app)

Temp: Has the jmeter script and the upload file.

In JMeter change your HTTP Request Default to the IP of the web server I have a shortcut to run jmeterw.cmd from the Temp folder. (I'm not certain if that drives the FileServerBase or not, but my file is found)

Though I'm still not certain if it's a JMeter bug or an IIS/ASP bug.

Edit 7:

Packet captures from the client and server Packet Captures

I just noticed that the Playback has "Content-Transfer-Encoding: binary", but normal and the recording do not. However, uploading as binary should be fine in this case. And even if the Type was wrong a corrupt file would still hit the server.

Edit 8:

The only differences that I can see are:

JMeter adds "charset=US-ASCII" on the Content-Type

JMeter adds "Content-Transfer-Encoding: binary" only on playback

JMeter boundaries are 32 characters, and random

Manual/working boundaries are 40 characters and start with lots of dashes

The Wireshark captures show that JMeter posts of my sample file are always 4 frames. around 650 bytes, 1450, 180, 38. Where the end boundary is almost by itself in the last frame. (from all of my fail captures that third frame is always 180, the others shift a bit)

The manual posts of my sample file are always 3 frames. around 450, 1450, 370.

IMHO the charset and binary shouldn't matter. I don't think frame count should matter. But at this point I am reaching for straws as to why this doesn't work. Could the boundary length really have something to do with it?

2

2 Answers

0
votes

You have recorded JMeter-originated request using Fiddler, now record the same request using real browser and inspect these 2 requests to find out any differences.

The requests should be identical (apart from boundary and ASP.NET_SessionId), if they are not - you will need to amend JMeter configuration accordingly.

My expectation is that you miss some correlation as ASP.NET web applications widely use i.e. __VIEWSTATE and __EVENTVALIDATION dynamic parameters and I don't see any sign of them.

If the same scenario works for the earlier JMeter versions and does not work for JMeter 3.2 it might be a regression issue which needs to be reported via JMeter Issue Tracker.

0
votes

I also observed same issue and resolved by referring below link How to send a POST request a file with Content-Type: application/octet-stream in Node js

Just select "use multipartform-data for POST" option of http sampler and remove content type from header