foreach loop fails to cast but manual casting and for loop work
Asked Answered
A

2

10

This code doesn't work when it finds a none empty file throwing

Unable to cast object of type 'System.String' to type 'System.Web.HttpPostedFile'.

foreach (System.Web.HttpPostedFile f in Request.Files)
{
   if (f.ContentLength > 0 && f.FileName.EndsWith(".pdf"))
   {
      //work done here
   }
}

Also I tested each item in Request.Files array an can be manually casted in the debug mode as below (with each index)

?(System.Web.HttpPostedFile)Request.Files[index]
{System.Web.HttpPostedFile}
    ContentLength: 536073
    ContentType: "application/pdf"
    FileName: "E:\\2.pdf"
    InputStream: {System.Web.HttpInputStream}

However, Following code works

for (index = 0; index < Request.Files.Count; index++)
{
   System.Web.HttpPostedFile f = Request.Files[index];
   if (f.ContentLength > 0 && f.FileName.EndsWith(".pdf"))
   {
      //work done here
   }
}

Any idea what is going wrong? Thanks

Aaron answered 8/2, 2013 at 13:54 Comment(0)
C
16

Request.Files is a HttpFileCollection, which is in turn a NameObjectCollectionBase. It isn't obvious, but the GetEnumerator() for that yields the keys for the collection - not the items themselves. So:

foreach(string key in Request.Files) {
    // fetch by key:
    var file = Request.Files[key];

    // ....
}

Not obvious, especially since the collection is non-generic IEnumerable rather than IEnumerable<string>.

It is at least documented:

This enumerator returns the keys of the collection as strings.

But: it was not unreasonable of you to suppose that iterating over the Files would give you the file objects.

Commission answered 8/2, 2013 at 14:3 Comment(4)
note: if it had been the generic version (IEnumerable<string>), then there's a good chance the compiler would have prevented you making this error; however, I suppose HttpFileCollection pre-dates generics.Commission
Then why it fails only when file is not empty? ex; if Request.Files[0] empty then it does not fail and goes through to the next one and if Request.Files[1] not empty the it fails. (or it iterates okay until it finds a non empty item)Aaron
@Aaron if there are no files, there is nothing to loop over, so no failed conversions. In other news, you can iterate over an empty int[] and convert each of the ints (all none of them) into SqlConnection and it won't care: because there is nothing to loop over.Commission
Worked perfectly for me. This error game when I tried accessing web api via a native HttpClient object in c# console applicationEquidistance
S
2

try like below.. it will work

foreach (string fName in Request.Files)
{
   System.Web.HttpPostedFile f = Request.Files[fName];
   if (f.ContentLength > 0 && f.FileName.EndsWith(".pdf"))
   {
      //work done here
   }
}

HttpFileCollection returns the keys of the files, not the HttpPostedFile objects.. so only it throws error..

Spermatophore answered 8/2, 2013 at 14:0 Comment(4)
I have fixed the issue with a for loop, I am asking why foreach loop fails.Aaron
@Aaron : Unable to cast object of type 'System.String' to type 'System.Web.HttpPostedFile'. is this your error...?Spermatophore
Yes. Also why it fails only when file is not empty?Aaron
It fails because Request.Files have the key values and it is string... (i.e) names... if it is empty then it does not try the For loop conditions.. if it have values then it try the conditions in for loop and try to assign that string to HttpPostedFile object... So only the error occurs...Spermatophore

© 2022 - 2024 — McMap. All rights reserved.