31

I need some help. I'm trying to upload files using <input type="file">. Here is my View:

@using (Html.BeginForm("BookAdd", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    <input type="file" name="files[0]" id="files[0]" />
    <input type="file" name="files[1]" id="files[1]" />
    <input type="submit" value="Upload Book" />
}

And here is an Action which should process uploaded file.

[HttpPost]
public ActionResult BookAdd(IEnumerable<HttpPostedFileBase> files)
{
    // some actions
    return View();
}

The problem is that "files" always contains two elements which are null. What can be done to fix it?

It's time for some news. It seems like I found the problem, but I still don't know how to fix it. It appears that despite the fact I'm using "multipart/form-data" here:

@using (Html.BeginForm("BookAdd", "Admin", FormMethod.Post, new { enctype="multipart/form-data" }))
{
    <input type="file" name="File" id="file1" />
    <input type="file" name="File" id="file2" />
    <input type="submit" value="Upload Book" />
}

Request.ContentType remains "application/x-www-forum-urlencoded" in controller..

Zano
  • 2,595
  • 27
  • 33
Roman
  • 1,396
  • 4
  • 15
  • 39
  • 5
    Don't worry, your English is perfect and your question is more than crystal clear. – Darin Dimitrov Nov 16 '11 at 22:46
  • you should really consider using a plugin. makes life easier, not to mention dealing with multiple browsers/runtimes. We use plupload. Works great. – RPM1984 Nov 16 '11 at 23:13

6 Answers6

37

The problem is that the NAME of the field need to match with the controller parameter. In your case is "files"... so your name attribute should be "files" also.

Romias
  • 13,783
  • 7
  • 56
  • 85
  • Thanks, this was the problem for me. – ajeetdl Aug 18 '13 at 17:50
  • The parameter was always null for me when doing an until the name attribute matched the function parameter name... – Cory R. King Jun 20 '14 at 20:11
  • Thanks, this fixed it for me, but now I have a new problem. Is there away to pass an id or attribute from the view that I can recognize and determine which file is which in the controller? – Mans Aug 21 '17 at 21:14
  • @Mans, You can pass a ViewModel as an additional parameter with any field, besides de IEnumerable param (or only a ViewModel with the HttpPostedFileBase inside). If you need to identify what file is what, you could add several file inputs, and that way you know which is which. – Romias Aug 21 '17 at 22:04
31

Just get rid of the square brackets in the names of your input fields:

@using (Html.BeginForm("BookAdd", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    <input type="file" name="files" id="file1" />
    <input type="file" name="files" id="file2" />
    <input type="submit" value="Upload Book" />
}

UPDATE:

After looking at the sample project you sent me the problem is that you have 2 nested forms. This is not allowed in HTML. You have one form in your _Layout.cshtml and another form in your BookAdd.cshtml view. That's the reason why despite the enctype="multipart/form-data" attribute on your inner form you were getting the wrong Request.ContentType. So you will have to unnest those forms if you want this to work. Also in the example you sent me your BookAdd controller action doesn't have the correct signature taking a list of files, but I guess that's due to some tests you were doing.

Guruprasad J Rao
  • 29,410
  • 14
  • 101
  • 200
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods ("."). Reference http://www.w3.org/TR/html4/types.html#case – SliverNinja - MSFT Nov 16 '11 at 22:58
  • I tried to do this, but it resulted in following: now I receive empty IEnumerable in controller (meaning Count = 0). – Roman Nov 16 '11 at 23:24
  • @Farrel, then you must be doing something different than what you have shown here. I have tested the code and it worked fine. The controller you are posting to must have the following signature: `public ActionResult BookAdd(IEnumerable files)`. – Darin Dimitrov Nov 17 '11 at 06:53
  • Actually the problem if already found. See my first message, it's updated. (Problem with Request.ContentType) – Roman Nov 17 '11 at 06:56
  • 1
    @Farrel, does the form have the `enctype` attribute when you look at the generated HTML source in the browser? – Darin Dimitrov Nov 17 '11 at 07:00
  • Do you mean the view itself? (the one containing ) If it is so, then no. – Roman Nov 17 '11 at 07:07
  • Ok, I understand what you meant. The page containing input hasn't enctype in it's HTML. – Roman Nov 17 '11 at 07:16
  • @Farrel, are you sure that you are using the correct signature of the `Html.BeginForm` method? There are many overloads. Be careful not to confuse between the `routeValues` and `htmlAttributes` argument. The one shown in the answer is correct. – Darin Dimitrov Nov 17 '11 at 07:17
  • Code looks exactly as you recommended to write.`@using (Html.BeginForm("BookAdd", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" })) { //some inputs}`. You think it can be interprated in wrong way? – Roman Nov 17 '11 at 07:36
  • @Farrel, could you send me your sample project by mail so that I can see what's wrong with it? – Darin Dimitrov Nov 17 '11 at 07:45
  • Yes, of couse. but there is one more problem. I don't know how, but I didnt noiticed that enctype actually presents in HTML. I guess it changes the situation. – Roman Nov 17 '11 at 07:54
  • @Farrel, I am afraid that from the information present here I cannot help you further since I cannot reproduce the problem. As I said it works for me. So there's probably something else going on in your project. – Darin Dimitrov Nov 17 '11 at 08:03
  • Ok, I'll send progect as fast as I can. – Roman Nov 17 '11 at 08:06
  • @Farrel, I got your project. The problem is that you have 2 nested forms. This is not allowed in HTML. You have one form in your `_Layout.cshtml` and another form in your `BookAdd.cshtml` view. That's the reason why despite the `enctype="multipatr/form-data"` attribute on your inner form you were getting the wrong Request.ContentType. So you will have to unnest those forms if you want this to work. Also in the example you sent me your BookAdd controller action doesn't have the correct signature taking a list of files, but I guess that's due to some tests you were doing. – Darin Dimitrov Nov 17 '11 at 09:16
  • Thanks a lot, @Darin. You're right and now everything works fine. – Roman Nov 17 '11 at 15:43
  • Thanks for saving my time. yes there was form inside form. – Rejwanul Reja Feb 07 '17 at 09:16
7

I was facing same problem but in my case i got a solution of this.

[HttpPost]
    public ActionResult Upload()
    {
        foreach (string file in Request.Files)
        {               
           fileurl = Request.Files[file];
        }
        return View();
    }

In Design View.Please Comment out Form Tag <%-- <form id="form1" runat="server">--%> if using Master Page...I hope Your problem will be solve...

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Upload
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

   <%-- <form id="form1" runat="server">--%>
  <% using (Html.BeginForm("Upload","Home",FormMethod.Post,new {enctype="multipart/form-data"}))
{ %>

<fieldset>
        <legend>Upload File</legend>
         <div>

          <p>
Select a File: <input type="file" name="FileUpload" />
<input type="submit" value="Upload" />
</p>
</div>
</fieldset>

<% } %>
4

Worth noting if you're using AJAX then the upload will always come through as null, so make sure no jquery AJAX is attached to the form submit.

mhapps
  • 93
  • 8
2

You must write some like this:

public class DocumentModelView 
{
        public HttpPostedFileBase File1 { get; set; }

        public HttpPostedFileBase File2 { get; set; }
}


@model Models.DocumentModelView

@using( Html.BeginForm( "Create", "Document", FormMethod.Post, new { enctype = "multipart/form-data" }) )
{
        <input type="file" name="File1" />
    <input type="file" name="File2" />
        <input type="submit" value="send" />
}


[HttpPost]
public ActionResult Create( DocumentModelView modelView )
{
.....
}
ADIMO
  • 1,107
  • 12
  • 24
  • But he wants to upload multiple files, not one. – Darin Dimitrov Nov 16 '11 at 22:45
  • Well, it still refuses to work. The only one thing I can think of is the variable name in controller. As I understood it can be any name (according to your example). Both File1 and File2 are null. – Roman Nov 16 '11 at 23:17
  • Yes, DocumentModelView is only a object (I have get it from an exist project) that contains file informations. – ADIMO Nov 16 '11 at 23:20
  • Actually I meant "modelView" by saying name. – Roman Nov 16 '11 at 23:28
1

In my case y had to use the name instead of id.

Like this:

<input type="file" id="upload" name="upload" />