ASP.NET MVC – Multiple Files Upload Bug or by-design issue?

Update: Yes. Kiran confirmed that it’s by design.

This is by design. This is part of System.Web and so we are not too inclined to fix this issue currently. A similar related issue was filed against Web API. You can check the resolution information on it.

http://aspnetwebstack.codeplex.com/workitem/188

Thanks,
Kiran

The issue is that when you http-post the request that contains a file html element then you got 1 for files.Count() but null for files.First().

One of my ex-colleagues faced this issue and share me this stackoverflow question posted by someone who is having a similar issue.

Here is the code for replicating the issue. (I will upload the sample to my blog’s git repository later.)

View

@using (Html.BeginForm("Upload", "Home", FormMethod.Post,
                       new { enctype = "multipart/form-data"}))
{
    <input name="files" type="file" multiple="multiple" />
    <input type="submit" value="Upload" />
}

Controller

[HttpPost]
        public ActionResult Upload(IEnumerable<HttpPostedFileBase> files) {
            if (files.Count() > 0) Console.WriteLine(files.Count()); // display 1
            if (files.Any()) Console.WriteLine(files.Any()); // display true
            if (files.First() == null) Console.WriteLine("first null"); // display "first null"
            return View();
        }

Screenshots

asp.net mvc file upload issues

Steps to replicate the issue

  1. Run the program
  2. Click on “Upload” without selecting any file.
  3. Check the value of “files” enumerable. You will see 1 for files.Count() and null for files.First().

Ok. I am not sure whether this is the bug or by-design issue so I posted the questions in MVC codeplex forum.

Request.Files

While I am waiting the reply from MVC team, I did a few experiments on this. The first thing that I did is to use Request.Files instead of binder so I changed the code as below.


[HttpPost]
public ActionResult Upload() {
var files = Request.Files;

return View();
}

Here is what I got. I believe that MVC code is also using Request.Files in binder to do the transformation from raw request to object. The count for Request.Files is also 1 even we don’t even select any file.

Request.Files return

 

As the Request.Files has a similar logic, I captured the raw http request in fidder and here is what I found.

POST http://localhost:17002/Home/Upload HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Referer: http://localhost:17002/
Accept-Language: en-US
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MALC; rv:11.0) like Gecko
Content-Type: multipart/form-data; boundary=—————————7de1d0220fe6
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Content-Length: 191
DNT: 1
Host: localhost:17002
Pragma: no-cache

—————————–7de1d0220fe6
Content-Disposition: form-data; name=”files”; filename=””
Content-Type: application/octet-stream
—————————–7de1d0220fe6–

You see, there is one empty item “filename=””” in form-data when we submit the request without selecting the file. This might be the reason why Request.Files is returning the count 1 instead of 0.

Request.Files (“file”) Vs HttpPostedFileBase (null)

Why do we got null for first index of “Files” enumerable?

HttpFileCollectionValueProvider.GetHttpPostedFileDictionary method create the directory based on http file request. HttpPostedFileBaseModelBinder.ChooseFileOrNull returns null value for filename=””. HttpFileCollectionValueProvider added that value to directory without checking the null value so I think it might be a by-design issue.

Here is the test code that shows null value.


[HttpPost]
public ActionResult Upload() {
var files = Request.Files;

//HttpFileCollectionValueProvider.GetHttpPostedFileDictionary
// build up the 1:many file mapping
List<KeyValuePair<string, HttpPostedFileBase>> mapping = new List<KeyValuePair<string, HttpPostedFileBase>>();
string[] allKeys = files.AllKeys;
for (int i = 0; i < files.Count; i++) {
string key = allKeys[i];
if (key != null) {
HttpPostedFileBase file = ChooseFileOrNull(files[i]);
}
}

return View();
}
internal static HttpPostedFileBase ChooseFileOrNull(HttpPostedFileBase rawFile) {
// case 1: there was no <input type="file" ... /> element in the post
if (rawFile == null) {
return null;
}

// case 2: there was an <input type="file" ... /> element in the post, but it was left blank
if (rawFile.ContentLength == 0 && String.IsNullOrEmpty(rawFile.FileName)) {
return null;
}

// case 3: the file was posted
return rawFile;
}

That’s all that I have tested.

If you are interested in this issue, you can probably check the following methods below.

  • HttpFileCollectionValueProvider.GetHttpPostedFileDictionary
  • HttpPostedFileBaseModelBinder.ChooseFileOrNull

I will update this blog post when I get any reply from MVC team.

 

2 thoughts on “ASP.NET MVC – Multiple Files Upload Bug or by-design issue?

  1. Musze sie wam pochwalić w końcu zrzucilam wage – 5 kilo.
    Przeszukalam chyba cały polski internet żeby znalezc cos na odchudzanie i znalazlam.
    Wygoglujcie sobie: xxally radzi jak szybko schudnąć

Leave a Reply

Your email address will not be published. Required fields are marked *