254

I am new to MVC 4 and I am trying to implement File Upload Control in my website. I am not able to find the mistake.I am getting a null value in my file.

Controller:

public class UploadController : BaseController
    {
        public ActionResult UploadDocument()
        {
            return View();
        }

       [HttpPost]
       public ActionResult Upload(HttpPostedFileBase file)
       {
           if (file != null && file.ContentLength > 0)
           {
               var fileName = Path.GetFileName(file.FileName);
               var path = Path.Combine(Server.MapPath("~/Images/"), fileName);
               file.SaveAs(path);
           }

           return RedirectToAction("UploadDocument");
        }
    }

View:

@using (Html.BeginForm("Upload", "Upload", FormMethod.Post, new { enctype = "multipart/form-data" }))
{ 
    <input type="file" name="FileUpload" />
    <input type="submit" name="Submit" id="Submit" value="Upload" />
}
Liam
  • 27,717
  • 28
  • 128
  • 190

5 Answers5

345

The Upload method's HttpPostedFileBase parameter must have the same name as the the file input.

So just change the input to this:

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

Also, you could find the files in Request.Files:

[HttpPost]
public ActionResult Upload()
{
     if (Request.Files.Count > 0)
     {
         var file = Request.Files[0];

         if (file != null && file.ContentLength > 0)
         {
            var fileName = Path.GetFileName(file.FileName);
            var path = Path.Combine(Server.MapPath("~/Images/"), fileName);
            file.SaveAs(path);
         }
     }

     return RedirectToAction("UploadDocument");
 }
Cristi Pufu
  • 9,002
  • 3
  • 37
  • 43
  • 2
    won't it through `Index out of bounds` exception in case there is no file in the `Request.Files` collection..? – shashwat Jan 09 '14 at 07:22
  • 2
    Actually it will throw `ArgumentOutOfRangeException`, but your are right, i updated – Cristi Pufu Jan 22 '14 at 17:30
  • 2
    Remember that the parameters of the Html.BeginForm are the action name and the controller name (without the 'controller' postfix. For instance: Home instead of HomeController). Another important thing is to not include the
    tag inside, because is the BeginForm that opens the tag
    – pocjoc Jun 04 '14 at 14:22
  • 6
    In other words - Your view model property name must match that of the input type name. If your `viewmodel` property is named `AgentPhoto` then you must have the following on your view: `` – Dayan Jul 09 '14 at 14:14
  • `var path = Path.Combine(Server.MapPath("~/Images/"), fileName);`, the class "Server" not found, which package use? – Danilo Pádua Sep 01 '15 at 14:51
  • Where is the connection between the Upload() method and the button. Should there be an onClick event? New to asp.net I am – pnizzle Nov 29 '18 at 03:09
  • To ensure the names match, I do it this way: – Nugsson Jun 17 '21 at 15:22
66

Clarifying it. Model:

public class ContactUsModel
{
    public string FirstName { get; set; }             
    public string LastName { get; set; }              
    public string Email { get; set; }                 
    public string Phone { get; set; }                 
    public HttpPostedFileBase attachment { get; set; }

Post Action

public virtual ActionResult ContactUs(ContactUsModel Model)
{
 if (Model.attachment.HasFile())
 {
   //save the file

   //Send it as an attachment 
    Attachment messageAttachment = new Attachment(Model.attachment.InputStream,       Model.attachment.FileName);
  }
}

Finally the Extension method for checking the hasFile

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace AtlanticCMS.Web.Common
{
     public static class ExtensionMethods 
     {
         public static bool HasFile(this HttpPostedFileBase file)
         {
             return file != null && file.ContentLength > 0;
         }        
     }
 }
Rehan Shah
  • 1,505
  • 12
  • 28
Bishoy Hanna
  • 4,539
  • 1
  • 29
  • 31
  • public HttpPostedFileBase attachment { get; set; }/ attachment is not an identify – Codeone Nov 24 '15 at 04:09
  • I think Cola is referring to the Attachment type not being defined. – Karson Dec 10 '15 at 14:23
  • 2
    View could be used as described by user2028367. Actually i forgot to include new { enctype = "multipart/form-data" } in Html.BeginForm part, so was unable to view the file in my action. Great answer. +1 for showing in Model class and Extension method. – ArjunArora Apr 01 '16 at 07:09
  • @BishoyHanna How I put, on my form, the attachment. For the other values razor provide to us a simple syntax, but how I do it for this file? – Denis V Jul 06 '16 at 17:02
  • Sorry @DenisV, can you clarify ? – Bishoy Hanna Jul 07 '16 at 09:04
  • @BishoyHanna, on our form, if we want a textfileld using the model, we put this code: `@Html.EditorFor(model => model.AssetName)` and for our file input? ` – Denis V Jul 07 '16 at 14:01
  • @BishoyHanna Good approach, but did not worked for me. May it be related to using AJAX? If so, which approach is better for posting multiple files to Controler in ASP.NET MVC5? Request.Files or this approach if it can works for AJAX of course. – Jack Oct 07 '16 at 17:37
  • 1
    hi, @ClintEastwood, that post was for uploading one file, I searched online for something that matches multiple uploads (for you) and found that one which I think would work. Again, its model based which is not using "Request.Files" http://stackoverflow.com/questions/36210413/multiple-file-upload-in-asp-net-mvc – Bishoy Hanna Oct 11 '16 at 01:02
17

View Page

@using (Html.BeginForm("ActionmethodName", "ControllerName", FormMethod.Post, new { id = "formid" }))
 { 
   <input type="file" name="file" />
   <input type="submit" value="Upload" class="save" id="btnid" />
 }

script file

$(document).on("click", "#btnid", function (event) {
        event.preventDefault();
        var fileOptions = {
            success: res,
            dataType: "json"
        }
        $("#formid").ajaxSubmit(fileOptions);
    });

In Controller

    [HttpPost]
    public ActionResult UploadFile(HttpPostedFileBase file)
    {

    }
Jagadisha B S
  • 673
  • 4
  • 11
  • 26
  • 2
    I agree with @Muflix , you don't need `AJAX` here. `Html.BeginForm` does the job already. AJAX is only needed if you don't want a redirect to the `
    `
    – jAC Jun 26 '17 at 11:32
  • 1
    Ajax is better for larger files since it allows you to enhance the user experience. – markthewizard1234 Sep 27 '17 at 08:58
6

you just have to change the name of your input filed because same name is required in parameter and input field name just replace this line Your code working fine

 <input type="file" name="file" />
Muhammad Asad
  • 1,772
  • 16
  • 23
2

I think, better way is use HttpPostedFileBase in your controller or API. After this you can simple detect size, type etc.

File properties you can find here:

MVC3 How to check if HttpPostedFileBase is an image

For example ImageApi:

[HttpPost]
[Route("api/image")]  
public ActionResult Index(HttpPostedFileBase file)  
{  
    if (file != null && file.ContentLength > 0)  
        try 
        {  
            string path = Path.Combine(Server.MapPath("~/Images"),  
               Path.GetFileName(file.FileName));

            file.SaveAs(path);  
            ViewBag.Message = "Your message for success";  
        }  
        catch (Exception ex)  
        {  
            ViewBag.Message = "ERROR:" + ex.Message.ToString();  
        }  
    else 
    {  
        ViewBag.Message = "Please select file";  
    }  
    return View();  
}

Hope it help.

Community
  • 1
  • 1
Petr Tomášek
  • 1,428
  • 16
  • 24