2

I've got a file upload module built into my MVC 4 application. Currently the system works fine if the user chooses a file and uploaded but if the user tries to click the Submit button with no file chosen my application is throwing an exception. I've looked in my code but I cannot figure out what's going on to cause the exception.

Here is the code I'm using.

FileUploadController Action: FileUpload:

 // Get the posted file and upload it
    [Authorize]
    [HttpPost]
    public ActionResult FileUpload(HttpPostedFileBase file)
    {
        //throw new Exception("Something went wrong");
        // Get the user ID
        int user_id;
        // Maximum file size 10MB
        //int maxSize = 10485760;
        // Get the maximum size allowed from web.config
        int maxSize = Int32.Parse(ConfigurationManager.AppSettings["MaxFileSize"]);

        user_id = WebSecurity.CurrentUserId;
        if (file.ContentLength > 0 && file.ContentLength < maxSize)
        {
            try
            {
                if (file.ContentLength > 0)
                {

                    var fileName = Path.GetFileName(file.FileName);
                    var fileType = Path.GetExtension(file.FileName);
                    var fileLength = file.ContentLength;

                    var uploadLocation = ConfigurationManager.AppSettings["UploadLocation"];

                    //Response.Write("Length: " + fileLength);
                    //Response.End();

                    switch (fileType.ToString())
                    {
                        // Potential bad extensions
                        // bat exe cmd sh php pl cgi 386 dll com torrent js app jar pif vb vbscript wsf asp cer csr jsp drv sys ade adp bas chm cpl crt csh fxp hlp hta inf ins isp jse htaccess htpasswd ksh lnk mdb mde mdt mdw msc msi msp mst ops pcd prg reg scr sct shb shs url vbe vbs wsc wsf wsh
                        // Block .exe etc  
                        case ".exe":
                        case ".cmd":
                        case ".msi":
                        case ".dll":
                        case ".com":
                        case ".torrent":
                        case ".js":
                        case ".wsh":
                        case ".vbs":
                        case ".asp":
                        case ".cs":
                        case ".vb":
                            ViewBag.Message = "ECTU Secure File Upload - File type not supported: '" + fileType.ToString() + "'";
                            return View();
                        default:
                            // Create a GUID for our stored filename
                            Guid fileGUID = Guid.NewGuid();
                            // Create the file path
                            //var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileGUID.ToString());
                            var path = Path.Combine(uploadLocation, fileGUID.ToString());
                            // Upload the file
                            file.SaveAs(path);
                            // Log in DB the file information that has been uploaded
                            int varLogFile = logFileInfo(user_id, fileName, path, fileType, fileGUID.ToString());
                            break;
                    }

                }
                else
                {
                    ViewBag.Message = "ECTU Secure File Upload - No file selected.";
                    return View();
                }
            }
            catch (Exception ex)
            {
                // No file selected
                // Return to view with error message
                ViewBag.Message = ex.ToString(); // "ECTU Secure File Upload - Please select a file to upload.";
                return View();
            }
        }
        else
        {
              ViewBag.Message = "ECTU Secure File Upload - File is too big: " + (file.ContentLength / 1024) + "kb";
              return View();
        }
        //returnto the view with a success message
        ViewBag.Message = "ECTU Secure File Upload - Upload Successful: " + file.FileName;
        return View();
    }

Razor html view : FileUpload.cshtml

@{
ViewBag.Title = "FileUpload";
}

<hgroup class="title">
    <h1>@ViewBag.Message</h1>
</hgroup>

<article>
<br />
<form action="" method="post" enctype="multipart/form-data">
  <input type="file" name="file" id="file" />
  <input type="submit" formaction="FileUpload" value="Submit">
</form>


<p><span class="instructions">Instructions: </span> Select a file to upload. Please note that executable (.exe) files are not supported. All files must be less than 1.9 Gb. Please refer to the user guide for more information.</p>

<p>@Html.ActionLink("Back to List", "Uploader", "Upload")</p>
</article>

Here is the full error code and stack trace:

Object reference not set to an instance of an object.
System.Web.HttpException (0x80004005): A public action method 'Uploadermvc error Object reference not set to an instance of an object' was not found on controller 'SecureFileUploadTraining.Controllers.UploadController'.

   at System.Web.Mvc.Controller.HandleUnknownAction(String actionName)

   at System.Web.Mvc.Controller.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult)

   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar)

   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()

   at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult)

   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar)

   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()

   at System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult)

   at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult)

   at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult)

   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar)

   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()

   at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)

   at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)

   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()

   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Thanks for any help you can give with this issue.

Connor McGill
  • 259
  • 4
  • 14

1 Answers1

1

Although the guys have already answered, you should implement a if-then-now catch to your method.

public ActionResult FileUpload(HttpPostedFileBase file)
{
   if(file == null)
   throw new ArgumentException("file")


   // Now perform the rest of the method.

}

You should be ensuring that the file has been uploaded client side, before this controller method has been hit.

Derek
  • 7,530
  • 9
  • 49
  • 80