I am trying to implement File Upload in MVC. I have the following code which works.
#using (Html.BeginForm("ActioName", "ControllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
<input type="file" name="file" />
<input type="submit" value="OK" class="button" />
</div>
}
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase file)
{
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
//do something here...
}
}
Now I want to add a dropdown box (to select the file type) and send that value along with the file to my Controller. How can I do that (send other form data along with the file)?
You should be able to add them to the view, include them in the POST and have MVC take care of the model binding:
#using (Html.BeginForm("ActioName", "ControllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
<input type="file" name="file" />
<select name="fileType">
<option value="JPG">Photo</option>
<option value="DOC">Word</option>
</select>
<input type="submit" value="OK" class="button" />
</div>
}
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase file, string fileType)
{
//Validate the fileType
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
//do something here...
}
}
I ended up doing it as follows it as follows. works good for me:
Created a Model:
public class FeeUpload
{
[Required (ErrorMessage="File Type required")]
public string fileType { get; set; }
[Required (ErrorMessage="file required")]
public HttpPostedFileBase File { get; set; }
}
View:
#using (Html.BeginForm("ActionName", "ControllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(false, "Please fix the following:")
<div>
<div>
#Html.DropDownListFor(model => model.fileType,
new List<SelectListItem>
{
new SelectListItem{ Text="xxx", Value = "yyy" },
new SelectListItem{ Text="xxx", Value = "yyy" },
new SelectListItem{ Text="xxx", Value = "yyy" }
}, "Select")
#*#Html.ValidationMessageFor(model => model.fileType)*#
</div>
<div>
#Html.TextBoxFor(model => model.File, new { type = "file" })
#*#Html.ValidationMessageFor(model => model.File)*#
<input type="submit" value="OK" class="button" id="btnsubmit" />
</div>
</div>
}
Controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult FeesAndCostsUpload(FeeUpload feeUploadFile)
{
if (ModelState.IsValid)
{
//do something with feeUploadFile.File and feeUploadFile.fileType
}
return View();
}
Try to not use Razor for the form
<form method="POST" data-url="#Url.Action("Action", "Controller")" enctype="multipart/form-data">
#Html.ValidationSummary(true)
<span class="btn btn-success fileinput-button">
<i class="fa fa-plus"></i>
<span>Add a file...</span>
#Html.TextBoxFor(model => model.Fichier, new { type = "file" })
</span>
<div class="form-group form-actions">
<div class="col-sm-offset-3 col-sm-9">
<input id="submit" type="submit" class="btn btn-primary" value='Value' />
</div>
</div>
</form>
worked for me
Related
Good day,
I am trying to upload an image from my view
#using (Html.BeginForm("CrearCurso", "ProfesorCurso", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
<label>Upload Image</label>
<div class="input-group">
<span class="input-group-btn">
<span class="btn btn-default btn-file">
Browse… <input type="file" id="imgInp">
</span>
</span>
<input type="text" class="form-control" readonly>
</div>
<img id='img-upload'/>
</div>
}
I have this controller in mvc
[HttpPost]
public ActionResult CrearCurso(CursoViewModel CursoViewModel, HttpPostedFileBase imgInp)
{
return View();
}
However when I inspect the HttpPsotedFileBase, it is empty. What is wrong here? thanks
Forms posts back the name/value pairs of its successful form controls. Your file input has no name attribute. Change it to
<input type="file" name="imgInp">
However, its better to strongly bind to your model, so add a
public HttpPostedFileBase ImgInp { get; set; }
property to your view model and use
#Html.TextBoxFor(m => m.ImgInp, new { type = "file" })
which will also allow you to add validation attributes to your file input if required
I am really confused by this error "not all code paths return a value" on my action PostResponse. I have stared at my model, controller and view for hours and I think I have all paths covered. Of course the project won't build, so I can't debug further.
My action
// POST: /Questions/ViewQuestion/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult PostResponse([Bind(Include = "UserId,QuestionID,Answer,Source,Status,DateStamp")] Response response)
{
if (ModelState.IsValid)
{
db.Responses.Add(response);
db.SaveChanges();
}
}
My view
#model Template.Models.Question
#using Microsoft.AspNet.Identity
#{
ViewBag.Title = "View question";
var qtype = Model.QuestionTypeId;
ViewBag.Number = Model.Id - 7;
}
#using (Html.BeginForm("Question", "ViewQuestion", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
<div>
<h4>Question ##ViewBag.Number</h4>
<hr />
<h1> #Model.Question1</h1>
</div>
<div class="form-group">
#switch (qtype)
{
case 1:
// Textbox
#Html.TextArea("Answer", new { #class = "form-control", rows = "4", col = "5" });
break;
case 2:
// Dropdown
<select class="form-control" id="Answer">
#foreach (var item in Model.QuestionOptions.OrderBy(o => o.QuestionOptionRanking))
{
<option value="#item.QuestionOption1">#item.QuestionOption1</option>
}
</select>
break;
case 3:
// Checkbox
<div class="checkbox">
#foreach (var item in Model.QuestionOptions.OrderBy(o => o.QuestionOptionRanking))
{
<input type="checkbox" name="Answer" value="#item.QuestionOption1" /> #item.QuestionOption1 <br />
}
</div>
break;
case 4:
// Radio buttons
foreach (var item in Model.QuestionOptions.OrderBy(o => o.QuestionOptionRanking))
{
<div class="radio">
<label>
<input type="radio" name="Answer" value="#item.QuestionOption1" />
#item.QuestionOption1
</label>
</div>
}
break;
}
</div>
#using Template.Models.Response
#Html.HiddenFor(r => r.Responses, new { UserId = User.Identity.GetUserId(), Source = "Web", Status = "New", DateStamp = System.DateTime.Now })
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Answer" />
</div>
</div>
<br />
<hr />
<p>
#Html.ActionLink("Previous", "ViewQuestion", new { id = Model.Id - 1 }) |
#Html.ActionLink("Next", "ViewQuestion", new { id = Model.Id + 1 })
</p>
The page displays perfectly, but I can't test the post action as I cannot build with the current error.
Worked it out; but it was almost from scratch, as I created a new ViewModel and used that to populate the responses.
[HttpPost]
public ActionResult ViewQuestion([Bind(Include = "QuestionId, Answer, UserId")] ResponseViewModel responseViewModel)
{
Response re = new Models.Response();
re.Answer = responseViewModel.Answer;
re.UserId = responseViewModel.UserId;
re.QuestionId = responseViewModel.QuestionId;
re.DateStamp = System.DateTime.Now;
db.Responses.Add(re);
db.SaveChanges();
return RedirectToAction("ViewQuestion");
}
Thanks for your input as your comments got the old head working again. Thanks!
Your PostResponse action, or method specifies an ActionResult as a return type, but does not actually return anything. You can resolve this by changing it from ActionResult to void
try
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult PostResponse([Bind(Include = "UserId,QuestionID,Answer,Source,Status,DateStamp")] Response response)
{
if (ModelState.IsValid)
{
db.Responses.Add(response);
db.SaveChanges();
}
else{
return View("Error");
}
}
I have the following _CreateOrEditPartial partial view which contain a text & a file upload:-
#model TMS.Models.DataCenter
#* This partial view defines form fields that will appear when creating and editing entities *#
#Html.AntiForgeryToken()
<div>
<span class="f">Name </span>
#Html.EditorFor(model=>model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div>
<span class="f">Data Center Picture </span>
<input type="file" name="DataCenterfile" />
</div>
and the following main view :-
#using (Html.BeginForm("Create","DataCenter", FormMethod.Post))
{
#Html.ValidationSummary(true)
#Html.Partial("_CreateOrEdit", Model)
<input type="submit" value="Create" class="btn btn-primary"/>
}
Which will call the following ActionMethod:-
[HttpPost]
[ValidateAntiForgeryToken]
[CheckUserPermissions(Action = "Edit", Model = "DataCenter")]
public ActionResult Create(DataCenter dc, HttpPostedFileBase DataCenterfile)
{
// Verify that the user selected a file
if (DataCenterfile != null && DataCenterfile.ContentLength > 0)
{
// extract only the fielname
var fileName = Path.GetFileName(DataCenterfile.FileName);
// store the file inside ~/App_Data/uploads folder
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
DataCenterfile.SaveAs(path);
}
but the datacenterfile will always be null .. can anyone advice what is causing this problem?
Thanks
You forgot to add the enctype attribute to your form.
Something like this:
#using (Html.BeginForm("actionName", "controllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
}
About enctype attribute: What does enctype='multipart/form-data' mean?
I simply tried this, but its not working, what is the problem in it,
MY index page:
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype = "multipart/from- data" }))
{
<div>
<h1 style="align-content: center; color: blueviolet">Application to upload files</h1>
</div>
<div>
<input type="file" id="file" name="file" />
<br />
<input type="submit" id="load" name="submit" value="Submit" />
</div>
}
And My controller is,
[HttpPost]
public ActionResult Upload()
{
string path = #"~/Content/Upload";
HttpPostedFileBase file = Request.Files["file"];
if (file != null)
file.SaveAs(path + file.FileName);
return Content("Sucess");
}
The path you are attempting to save your file to looks wrong. Try with MapPath:
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
string path = Server.MapPath("~/Content/Upload");
if (file != null)
{
file.SaveAs(Path.Combine(path, file.FileName));
}
return Content("Sucess");
}
Also make sure that you have used the correct enctype attribute in your form:
enctype = "multipart/form-data"
instead of:
enctype = "multipart/from- data"
I have a model (simplified, removing extraneous properties):
public class SubmitModel
{
[Required]
[DataType("FileUpload")]
[Display(Name = "Formatted Data File")]
public HttpPostedFileBase FormattedDataFile { get; set; }
}
A controller:
[HttpPost]
public ActionResult Submit(SubmitModel model)
{
if (this.ModelState.IsValid)
{
//...
}
return this.View(model);
}
A FileUpload view:
#{
IDictionary<string, object> htmlAttributes = Html.GetUnobtrusiveValidationAttributes(string.Empty);
}
<input type="file" id="#this.ViewData.TemplateInfo.GetFullHtmlFieldId(string.Empty)" name="#this.ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty)" #(new MvcHtmlString(htmlAttributes.ToHtmlAttributesString())) />
#Html.ValidationMessage(string.Empty)
And a simple view:
#model SubmitModel
#using (Html.BeginForm())
{
<div class="Form">
#Html.EditorForModel()
<div class="Footer">
<button class="Button" data-options='{ "icons": { "primary": "ui-icon-disk" } }'>Submit</button>
</div>
</div>
}
Which renders to this HTML:
<form action="/Data/Submit" method="post">
<div class="Form">
<div class="Item">
<div class="Label Required">Formatted Data File:</div>
<div class="Input">
<input type="file" id="FormattedDataFile" name="FormattedDataFile" data-val-required="The Formatted Data File field is required." data-val="true" />
<span class="field-validation-error" data-valmsg-for="FormattedDataFile" data-valmsg-replace="true">The value 'Test.xlsx' is invalid.</span>
</div>
</div>
<div class="Footer">
<button class="Button" data-options='{ "icons": { "primary": "ui-icon-disk" } }'>Submit</button>
</div>
</div>
</form>
Upon clicking Submit, I'm brought to the proper controller/action and my model's FormattedDataFile property is null. The ModelState is invalid, saying that "The Formatted Data File field is required." This same code worked fine in some MVC-3 projects I've done - is there anything different regarding this in MVC-4?
i think you are missing enctype="multipart/form-data" in the form
http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2