简体   繁体   中英

File upload error in asp.net mvc controller ('HttpRequestMessage' does not contain a definition for 'Files'

I have a controller link to an input element for uploading. In my controller I am getting a weird error that I do not quite understand. Severity Code Description Project Path File Line Suppression State

Error CS1061 'HttpRequestMessage' does not contain a definition for 'Files' and no accessible extension method 'Files' accepting a first argument of type 'HttpRequestMessage' could be found (are you missing a using directive or an assembly reference?) SimSentinel C:\\Users\\tsach\\Source\\Workspaces\\SIMSentinelv2\\Website\\SimSentinel\\SimSentinel\\Controllers C:\\Users\\tsach\\Source\\Workspaces\\SIMSentinelv2\\Website\\SimSentinel\\SimSentinel\\Controllers\\BulkSMSUploadController.cs

    using System.Data;
    using System.Linq;
    using System.Web.Http;
    using System.Web.Security;
    using Repositories.Interfaces;
    using Repositories.Interfaces.Dtos;
    using SimSentinel.Models;
    using System;
    using System.Text.RegularExpressions;
    using Newtonsoft.Json.Linq;
    using Newtonsoft.Json.Schema;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    //using System.Web.Http.HttpPut;


    namespace SimSentinel.Controllers
    {
        [System.Web.Http.Authorize]
        public class BulkSMSUploadController : ApiController
        {
          public ActionResult Index()
          {
             //ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

             //return View();
             return null; 
          }

          [System.Web.Mvc.HttpPost]
          public ActionResult UploadFiles()
          {
             if (Request.Files.Count <= 0)
             {
                return Json("No files selected.");
             }
             else
             {
                try
                {
                   HttpFileCollectionBase files = Request.Files;
                   for (int i = 0; i < files.Count; i++)
                   {
                      string path = AppDomain.CurrentDomain.BaseDirectory + "Uploads/";
                      string filename = Path.GetFileName(Request.Files[i].FileName);

                      HttpPostedFileBase file = files[i];
                      string fname;
                      if (Request.Browser.Browser.ToUpper() == "IE" || Request.Browser.Browser.ToUpper() == "INTERNETEXPLORER")
                      {
                         string[] testfiles = file.FileName.Split(new char[] { '\\' });
                         fname = testfiles[testfiles.Length - 1];
                      }
                      else
                      {
                         fname = file.FileName;
                      }

                      fname = Path.Combine(Server.MapPath("~/Uploads/"), fname);
                      file.SaveAs(fname);
                   }

                   return Json("File Uploaded Successfully!");
                }
                catch (Exception ex)
                {
                   return Json("Error occurred. Error details: " + ex.Message);
                }
             }
          }

          //public ActionResult About()
          //{
          //   ViewBag.Message = "Your app description page.";

          //   return View();
          //}
       }
    }

So after all this I have adjusted my controller. See code below which works however it redirects to the actual controller and that is a problem in a SPA application. In addition, the file also saves in a wierd format almost like a randomly generated string like BodyPart_2ea18b56-0c11-41f6-81ff-204bb377cbbf

using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;

public class Upload2Controller : ApiController
{
   public async Task<HttpResponseMessage> PostFormData()
   {
      // Check if the request contains multipart/form-data.
      if (!Request.Content.IsMimeMultipartContent())
      {
         throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
      }

      string root = HttpContext.Current.Server.MapPath("~/Files");
      var provider = new MultipartFormDataStreamProvider(root);

      try
      {
         // Read the form data.
         await Request.Content.ReadAsMultipartAsync(provider);

         // This illustrates how to get the file names.
         foreach (MultipartFileData file in provider.FileData)
         {
            Trace.WriteLine(file.Headers.ContentDisposition.FileName);
            Trace.WriteLine("Server file path: " + file.LocalFileName);
         }
         return Request.CreateResponse(HttpStatusCode.OK);
      }
      catch (System.Exception e)
      {
         return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
      }
   }

}

You should be careful on following steps.

  • Make sure your form html element has enctype = "multipart/form-data" So it should be something like <form action="someaction" enctype = "multipart/form-data"> </form>

I usually use html helper..

@using (Html.BeginForm("Index", "JobApplication", FormMethod.Post, new { @enctype = "multipart/form-data", @id = "myForm", @class = "form-horizontal" }))
    {
// your input datas
}
  • If you would like to post image or some document, insead of using request, you should use public HttpPostedFileBase File { get; set; } public HttpPostedFileBase File { get; set; } public HttpPostedFileBase File { get; set; } in your ViewModel. Then you can easily use it on your razor.

    @Html.TextBoxFor(m => m.File, new { @type = "file", @onchange = "SomeValidationOnClientSide(this);"})

On the backend side you can validate your case. In my case I only accept PDF files..

if ((from file in model.Files where file != null select file.FileName.Split('.')).Any(arr => arr[arr.Length - 1].ToLower() != "pdf"))
        {
            ModelState.AddModelError(string.Empty, "We only accept PDF files!");
            return View(model);
        }
        if (model.Files.Count() > 2)
        {
            ModelState.AddModelError(string.Empty,
                "You have exceeded maximum file upload size. You can upload maximum 2 PDF file!");
            return View(model);
        }

Edit: I see that you implemented ApiController instead of Contoller. So I understand that you are developing WEB.API, you should add this into question tags as well.

If you would like to develop ApiController, you should send byte[] and process this byte[] into your apiController.

From what I see your controller implements Web API controller (ie using ApiController.Request ), which has definition as shown below:

public System.Net.Http.HttpRequestMessage Request { get; set; }

The return type is HttpRequestMessage which doesn't have Files property, as opposed to intended HttpRequestBase that implemented as return type of Controller.Request property below:

public System.Web.HttpRequestBase Request { get; }

To solve this issue, you need to inherit from System.Web.Mvc.Controller base class and move Web API requests to another class which inherits ApiController , because you cannot inherit both System.Web.Mvc.Controller and System.Web.Http.ApiController on the same class:

namespace SimSentinel.Controllers
{
   public class BulkSMSUploadController : Controller
   {
      [System.Web.Mvc.HttpPost]
      public ActionResult UploadFiles()
      {
         if (Request.Files.Count <= 0)
         {
            return Json("No files selected.");
         }
         else
         {
            try
            {
               HttpFileCollectionBase files = Request.Files;
               for (int i = 0; i < files.Count; i++)
               {
                  string path = AppDomain.CurrentDomain.BaseDirectory + "Uploads/";
                  string filename = Path.GetFileName(Request.Files[i].FileName);

                  HttpPostedFileBase file = files[i];
                  string fname;
                  if (Request.Browser.Browser.ToUpper() == "IE" || Request.Browser.Browser.ToUpper() == "INTERNETEXPLORER")
                  {
                     string[] testfiles = file.FileName.Split(new char[] { '\\' });
                     fname = testfiles[testfiles.Length - 1];
                  }
                  else
                  {
                     fname = file.FileName;
                  }

                  fname = Path.Combine(Server.MapPath("~/Uploads/"), fname);
                  file.SaveAs(fname);
               }

               return Json("File Uploaded Successfully!");
            }
            catch (Exception ex)
            {
               return Json("Error occurred. Error details: " + ex.Message);
            }
         }
      }
   }

   [System.Web.Http.Authorize]
   public class BulkSMSUploadWebApiController : ApiController
   {
       public IHttpActionResult Index()
       {
           return null; 
       }
   }
}

If you want to upload file using Web API controller, you should use HttpResponseMessage to retrieve file details with MultipartFileData as provided in this example (make sure you're checking against IsMimeMultipartContent first).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM