Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC 3 file upload and model binding

I have a form upload that works but I would like to pass model information for my database to save the file with a different name of course.

Here is my Razor view:

@model CertispecWeb.Models.Container  @{   ViewBag.Title = "AddDocuments"; }  <h2>AddDocuments</h2>  @Model.ContainerNo  @using (Html.BeginForm("Uploadfile", "Containers", FormMethod.Post,              new { enctype = "multipart/form-data" })) {     <input type='file' name='file' id='file' />     <input type="submit" value="submit" /> } 

Here is my Controller:

[HttpPost] public ActionResult Uploadfile(Container containers, HttpPostedFileBase file) {      if (file.ContentLength > 0)      {         var fileName = Path.GetFileName(file.FileName);         var path = Path.Combine(Server.MapPath("~/App_Data/Uploads"),                        containers.ContainerNo);         file.SaveAs(path);      }       return RedirectToAction("Index"); } 

The model information is not passed through to the controller. I have read that I might need to update the model, how would I do this ?

like image 539
Francis Avatar asked Jan 24 '11 16:01

Francis


2 Answers

Your form doesn't contain any input tag other than the file so in your controller action you cannot expect to get anything else than the uploaded file (that's all that's being sent to the server). One way to achieve this would be to include a hidden tag containing the id of the model which will allow you to retrieve it from your datastore inside the controller action you are posting to (use this if the user is not supposed to modify the model but simply attach a file):

@using (Html.BeginForm("Uploadfile", "Containers", FormMethod.Post, new { enctype = "multipart/form-data" })) {     @Html.HiddenFor(x => x.Id)     <input type="file" name="file" id="file" />     <input type="submit" value="submit" /> } 

and then in your controller action:

[HttpPost] public ActionResult Uploadfile(int id, HttpPostedFileBase file) {     Containers containers = Repository.GetContainers(id);     ... } 

On the other hand if you wanted to allow the user to modify this model then you will need to include the proper input fields for each field of your model that you want to be sent to the server:

@using (Html.BeginForm("Uploadfile", "Containers", FormMethod.Post, new { enctype = "multipart/form-data" })) {     @Html.TextBoxFor(x => x.Prop1)     @Html.TextBoxFor(x => x.Prop2)     @Html.TextBoxFor(x => x.Prop3)     <input type="file" name="file" id="file" />     <input type="submit" value="submit" /> } 

and then you will have the default model binder reconstruct this model from the request:

[HttpPost] public ActionResult Uploadfile(Container containers, HttpPostedFileBase file) {     ... } 
like image 101
Darin Dimitrov Avatar answered Oct 09 '22 10:10

Darin Dimitrov


Solved

Model

public class Book { public string Title {get;set;} public string Author {get;set;} } 

Controller

public class BookController : Controller {      [HttpPost]      public ActionResult Create(Book model, IEnumerable<HttpPostedFileBase> fileUpload)      {          throw new NotImplementedException();      } } 

And View

@using (Html.BeginForm("Create", "Book", FormMethod.Post, new { enctype = "multipart/form-data" })) {            @Html.EditorFor(m => m)       <input type="file" name="fileUpload[0]" /><br />            <input type="file" name="fileUpload[1]" /><br />            <input type="file" name="fileUpload[2]" /><br />             <input type="submit" name="Submit" id="SubmitMultiply" value="Upload" /> } 

Note title of parameter from controller action must match with name of input elements IEnumerable<HttpPostedFileBase> fileUpload -> name="fileUpload[0]"

fileUpload must match

like image 25
isxaker Avatar answered Oct 09 '22 09:10

isxaker