ASP.NET MVC 3 - File Upload - asp.net-mvc-3

I have an ASP.NET MVC 3 application. I need to implement a file uploader action within it. For some reason, when I post my form, the Request.Files collection is empty. I have been able to confirm this by setting a breakpoint. So I know that I'm reaching the action. However, I can't figure out why the Request.Files collection is empty. Here are my relevant HTML, AreaRegistration, and Controller snippets.
index.html
<form action="/files/upload/uniqueID" method="post" enctype="multipart/form-data">
<div>Please choose a file to upload.</div>
<div><input id="fileUpload" type="file" /></div>
<div><input type="submit" value="upload" /></div>
</form>
MyAreaRegistration.cs
context.MapRoute(
"FileUpload",
"files/upload",
new { action = "UploadFile", controller = "Uploader" }
);
UploaderController.cs
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UploadFile(int uniqueID)
{
foreach (string file in Request.Files)
{
// I never get here :(
}
return View();
}
I have not made any changes to the default web.config file. Is there some setting I need to add? I can't figure out why the Request.Files collection would be empty. Can someone please help me?
Thank you so much!

You should use HttpPostedFileBase for you controller and do something like that
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/"), fileName);
file.SaveAs(path);
}
return RedirectToAction("Index");
}
And for the view
<form action="" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<input type="submit" />
</form>
Check Phil Haack blog here for this problem: Uploading a File (Or Files) With ASP.NET MVC

I believe the problem is with your action attribute in your <form /> tag:
action="/files/upload/uniqueID"
I think upon post it is trying to pass the string "uniqueID" to your Action method. When you hit your breakpoint, what is the value of your uniqueID parameter set to when you reach the action method UploadFile()?
Use the HtmlHelper.BeginForm() method to use Razor to construct the form.

Related

Pass image data from view to controller on update button click in update page

Here on the update page load the image is displayed on the web page .
On update button click how to pass the image data(IFormFile) form view to controller.
If you want to pass IFormFile from view to controller,you can use a input which type is file,view cannot pass a <img/> to controller.Here is a demo:
View:
<form method="post" enctype="multipart/form-data">
<input type="file" name="image"/>
<input type="submit" value="submit"/>
</form>
Controller:
[HttpPost]
public IActionResult Main(IFormFile image)
{
return View();
}
result:
Or you can pass a path to controller,and controller get the file with a path.
Image:
View:
<form method="post" enctype="multipart/form-data">
<input name="image" value="1.jpg" hidden/>
<img src="~/images/1.jpg" />
<input type="submit" value="submit" />
</form>
Controller:
[HttpPost]
public IActionResult Main(string image)
{
string path = "./wwwroot/images/" + image;
IFormFile File;
using (var stream = System.IO.File.OpenRead(path))
{
File = new FormFile(stream, 0, stream.Length, null, Path.GetFileName(stream.Name));
}
return View();
}
result:

Thymeleaf - Button click to call http delete method

I would like to call the url via http delete method. I tried th:onclick and th:action but not working.
html code:
<button id="delete" name="delete" th:onclick="#{'/foos/{id}'(id=${foo.id})}" th:method="delete">Delete</button>
controller code:
#RequestMapping(value="/foos/{id}", method = RequestMethod.DELETE)
#ResponseBody
public String delete(#PathVariable String id) {
studentService.delete(id);
return "Successfully deleted";
}
I think you will need a form for your transaction. And also this hidden input field.
<form action="#" th:action="#{'/delete/{id}'(id=${foo.id})}" th:method="delete" >
<input type="hidden" name="_method" value="delete" />
<button type="submit" id="submitButton"> </button>
</form>
The th:method="delete" creates the hidden input field automatically for you. If you add it manually as well you will have it twice. Check the source code.
I still got the POST Error message after the recommendations here. I found out Spring ignores those hidden fields by default. The solution is to activate it in your application.properties file:
spring.mvc.hiddenmethod.filter.enabled=true
My working code in my application looks like this:
Form:
<form action="#" th:action="#{'/books/delete/{id}'(id=${book.id})}" th:method="delete" >
<button type="submit" class="btn">
Delete
</button>
</form>
Controller:
#RequestMapping(value="/books/delete/{id}", method = RequestMethod.DELETE)
public String deleteBook(#PathVariable Long id) {
bookService.deleteBook(id);
return "books";
}

Uploading files with MVC 3 ajax style

Maybe it's just me but I'm trying to use a jQuery dialog to capture a file the user wants to upload. It must be supported by IE9. IE9 doesn't support the FormData object which is used in many examples and 3rd party tools I have came across. So in order to make my request not refresh the whole page I have to put my upload into an iFrame? Really? I know I can get some flash uploader but flash isn't supported on our site so that's out of the question right now.
Please.. please someone tell me I'm doing this wrong and there's an easier way because I can't seem to find it.. not one that will work on IE9 at least.
Form
<form action="/ControllerName/ActionName" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<input type="submit" name="submit" value="Submit" />
</form>
Then into an iFrame like this
<iframe src="myUrl"></iframe>
View:
#using (Html.BeginForm("FileUpload","Message",FormMethod.Post,new { enctype="multipart/form-data"})) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Message</legend>
//your html here
<input type="file" name="files"/>
</fieldset>
Controller:
[HttpPost]
public ActionResult FileUpload(FormCollection values, IEnumerable<HttpPostedFileBase> files)
{
//do what you want with form values then for files
foreach (var file in files)
{
if (file.ContentLength > 0)
{
byte[] fileData = new byte[file.ContentLength];
file.InputStream.Read(fileData, 0, file.ContentLength);
//do what you want with fileData
}
}
}
I provide multiple files upload so i use
IEnumerable<HttpPostedFileBase> files
if you want only a single file then use only
HttpPostedFileBase file
and in your view change input type to
<input type="file" name="file"/>
Simple as that.
Regards
EDITED:
Take a look at more good examples:
http://www.strathweb.com/2012/04/html5-drag-and-drop-asynchronous-multi-file-upload-with-asp-net-webapi/
http://css.dzone.com/articles/implementing-html5-drag-drop
Regards

ASP.Net MVC3: how to send different values for same field?

How can I send to action of controller different values for same field? Which input parameters should I define in action? And how can I show url with different values of identical fields in querystring? I want to get such url: site.com/directory?metro=2&metro=3
Thanks!
Here's an example of how this would be done in the case of checkboxes. Note that you wouldn't see the same querystring parameter repeated in the case of a GET request. Instead you would see "?metros=1,3" if checkboxes 1 and 3 were checked.
HTML
<form action="http://site.com/directory" method="get">
<input type='checkbox' name='metros' value='1' />
<input type='checkbox' name='metros' value='2' />
<input type='checkbox' name='metros' value='3' />
</form>
Controller
public class DirectoryController : Controller {
public ActionResult Index(IEnumerable<int> metros) {
foreach (var metro in metros) {
// do something
}
return View();
}
}

ASP.NET MVC 3 Multiple Submit Inputs in One Form

I am currently having an issue with multiple action buttons being in the same form.
The first button would perform verification while the second button would save profile. The third would simple redirect the user out of the page, but they are still required to go through controller some tracking purposes. Last button is delete. Because they are placed together and I do need ModelBinding passed through POST, it's impossible to separate them into multiple forms.
Currently, in order to differentiate which action is being clicked, I have a hidden input in my form and onclick, javascript would update the hidden input so that it will be passed back to the controller.
The reason I did this was because for some weird reasons, FormCollection doesn't want to hold my submit values. I tried accessing buttons in controller via
formCollection["verify"]
But it turns out to be null. Both id and name of the input submit is set to verify.
I also tried a lot of other suggestions like this and this but to no avail. Is there a better approach to my problem without using javascript to alter hidden inputs?
The best approach is to have separate actions handling the different button calls as explained in this article.
If you want to have one ugly action doing all the stuff then you could give your submit buttons names:
#using (Html.BeginForm())
{
... input fields for the model
<button type="submit" name="btn" value="verify">Verify data</button>
<button type="submit" name="btn" value="save">Save data</button>   
<button type="submit" name="btn" value="redirect">Redirect</button>
}
You don't need any hidden fields or javascript. And then in your controller action you would check for the value of the btn parameter (which obviously will be part of you view model):
[HttpPost]
public ActionResult Foo(MyViewsModel model)
{
if (model.Btn == "verify")
{
// the Verify button was clicked
}
else if (model.Btn == "save")
{
// the Save button was clicked
}
else if (model.Btn == "redirect")
{
// the Redirect button was clicked
}
else
{
// ??? throw
}
...
}
Of course if you follow my advice and separate your actions (as outlined in the article):
#using (Html.BeginForm("Action", "Home"))
{
... input fields for the model
<input type="submit" name="verify" value="Verify data" />
<input type="submit" name="save" value="Save data" />
<input type="submit" name="redirect" value="Redirect" />
}
and then:
[HttpParamAction]
[HttpPost]
public ActionResult Verify(MyViewModel model)
{
...
}
[HttpParamAction]
[HttpPost]
public ActionResult Save(MyViewModel model)
{
...
}
[HttpParamAction]
[HttpPost]
public ActionResult Redirect(MyViewModel model)
{
...
}
which is a far cleaner code which doesn't violate the Single Responsibility Principle.
I do something slightly different;
<input type="submit" name="submit" value="Save Draft" />
<input type="submit" name="submit" value="Publish" />
Then you can get at the values using;
FormCollection["submit"]
Thanks,
Matt
<input type="submit" name="nameONE" />
<input type="submit" name="nameTWO" />
[HttpPost, ActionName("OrginalActionName")]
[FormValueRequired("nameONE")]
public ActionResult WhateverYouWantONE(type name)
{
code...
}
[HttpPost, ActionName("OrginalActionName")]
[FormValueRequired("nameTWO")]
public ActionResult WhateverYouWantTWO(type name)
{
code...
}

Resources