MVC HttpPost not working - c#

I have a null object reference exception in executing this code. I have a file html control and my Razor code looks like this:
#using (Html.BeginForm("AddFiles", "AdministerFiles", FormMethod.Post))
{
<p><label for="filename">Filename : </label><input type="text" name="filename" /></p>
<p><label for="description">Description : </label><input type="text" name="description" /></p>
<p><input type="file" name="file" id="file" /> </p>
<p><input type="hidden" value="#Model[2]" name="catid"/></p>
<input type="submit" value="Upload Now!" />
<input type="reset" value="Reset" />
}
My AdministerFilesController is this:
[HttpPost]
public ActionResult AddFiles(HttpPostedFileBase file, int catid, string description)
{
// Verify that the user selected a file {
if (file != null && file.ContentLength > 0)
{
// extract only the filename
var filename = Path.GetFileName(file.FileName);
// store the file inside ~/App_Data/Uploads folder
var path = Path.Combine(Server.MapPath("~/App_Data/Uploads"), filename);
file.SaveAs(path);
}
RefDataLinks_mst fileDetails = new RefDataLinks_mst()
{
LastModified = new DateTime(2012,1,1),
CategoryID = catid,
DataFileName = Path.GetFileName(file.FileName),
DataTitle = "SAMPLETITLE",
DataID = ((new Random()).Next(100, 1000)),
DataFilePath = "Sample/Path",
Description = description,
UpdatedBy = "Arjel",
FileSize = file.ContentLength
};
bool b = ServiceReferenceHelper.AddFile(fileDetails);
// Redirect back to the index action to show the form once again
return Redirect("AddFiles?catid=" + catid); //both works
//return RedirectToAction("ViewDataFiles", new { catid = catid });
}
The data from catid and description are received but the file references to a null object. What could be the problem?

Uploads actually require you to specify the enctype attribute on the form. Here's an example of how to do that:
#using (Html.BeginForm("AddFiles", "AdministerFiles", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
...
}

Related

ASP.Net MVC 5 with DropZone Can't Send Additional Parameters to Controller

Ok, I am sure this already has an answer somewhere, but I can honestly tell you that everything I have tried, has failed. Here is my current configuration:
Shared _Layout.cshtml (below the footer)
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<script src="https://unpkg.com/dropzone#5/dist/min/dropzone.min.js"></script>
#await RenderSectionAsync("Scripts", required: false)
Images View
#model NewProductVM
<form id="form2" method="post" enctype="multipart/form-data" data-parsley-validate class="form-horizontal form-label-left">
<div class="form-group">
<label class="control-label col-md-2" for="first-name">
<span class="required">*</span>
</label>
<input type="hidden" value="#Model.Id" />
<div class="col-md-6" id="dropzone">
<div action="UploadFiles" class="dropzone" id="uploader">
Drop files here or click to upload.<br>
</div>
</div>
</div>
</form>
Products Controller
[HttpPost]
public async Task<IActionResult> UploadFiles(string Id)
{
bool bSuccess = true;
_ConnectionString = _Configuration.GetConnectionString("StorageConnectionString");
_ContainerName = _Configuration.GetValue<string>("StorageContainerName");
string uploads = Path.Combine(_hostingEnvironment.ContentRootPath, "Uploads");
if (!Directory.Exists(uploads))
Directory.CreateDirectory(uploads);
foreach (var iFormFile in Request.Form.Files)
{
if (iFormFile.Length > 0)
{
if (StorageHelper.IsImage(iFormFile))
{
var filePath = Path.Combine(uploads, iFormFile.FileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await iFormFile.CopyToAsync(stream);
}
bSuccess = await StorageHelper.UploadFileToStorage(iFormFile, filePath, _ConnectionString, _ContainerName);
System.IO.File.Delete(filePath);
ProductImage productImage = new ProductImage
{
ProductId = int.Parse(Id),
ImageURL = $"{_Configuration.GetValue<string>("StorageContainerURL")}/{iFormFile.FileName}"
};
await _imageService.AddNewImageAsync(productImage);
}
}
}
return RedirectToAction("Index");
}
I would really like to pass the entire NewProductVM model to the UploadFiles method, but there are not very many properties in the view model, so I could pass each property individually.
Right now I am taking someones suggestion to create a hidden form field and add a value I want to pass to the controller as a form field, but the parameter value in the UploadFiles method is null. I have also tried using asp-route-id="#Model.Id". When I did that, the value of id was 0 in the controller method.
Anyone have any suggestions?
Ok, I finally found the answer and I cannot believe how simple it was. I have been working on this for several hours. I found the answer here: https://social.msdn.microsoft.com/Forums/en-US/a87c6936-c0b5-4f47-b074-dbaf4c154cdd/id-parameter-returning-null-after-using-formdataappend-to-append-id-to-model-id-in-mvc-5?forum=aspmvc
This is what I did:
Images.cshtml
<form id="form2" method="post" enctype="multipart/form-data" data-parsley-validate class="form-horizontal form-label-left">
<div class="form-group">
<label class="control-label col-md-2" for="first-name">
<span class="required">*</span>
</label>
<div class="col-md-6" id="dropzone">
<div action="UploadFiles?Id=#Model.Id" class="dropzone" id="uploader">
Drop files here or click to upload.<br>
</div>
</div>
</div>
</form>
ProductsController.cs
[HttpPost]
public async Task<IActionResult> UploadFiles(int Id)
{
bool bSuccess = true;
_ConnectionString = _Configuration.GetConnectionString("StorageConnectionString");
_ContainerName = _Configuration.GetValue<string>("StorageContainerName");
//int Id = int.Parse(fc["Id"]);
string uploads = Path.Combine(_hostingEnvironment.ContentRootPath, "Uploads");
if (!Directory.Exists(uploads))
Directory.CreateDirectory(uploads);
foreach (var iFormFile in Request.Form.Files)
{
if (iFormFile.Length > 0)
{
if (StorageHelper.IsImage(iFormFile))
{
var filePath = Path.Combine(uploads, iFormFile.FileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await iFormFile.CopyToAsync(stream);
}
bSuccess = await StorageHelper.UploadFileToStorage(iFormFile, filePath, _ConnectionString, _ContainerName);
System.IO.File.Delete(filePath);
//ProductImage productImage = new ProductImage
//{
// ProductId = Id,
// ImageURL = $"{_Configuration.GetValue<string>("StorageContainerURL")}/{iFormFile.FileName}"
//};
//await _imageService.AddNewImageAsync(productImage);
}
}
}
return RedirectToAction("Index");
}
The part that really made it work was action="UploadFiles?Id=#Model.Id".
So basically, I am using the action to pass the values I want to my controller method.

Cannot add image asp.net mvc 5

I have a model of Client with a property — public string PhotoPath {get; set;}.
I'm trying to add an image in Create httppost method:
public ActionResult FileUpload(HttpPostedFileBase file, Guid id)
{
if (file != null)
{
string pic = System.IO.Path.GetFileName(file.FileName);
string path = System.IO.Path.Combine(
Server.MapPath("~/images/profile"), pic);
file.SaveAs(path);
Client client = db.Clients.Find(id);
if (client == null) return HttpNotFound();
client.PhotoPath = path;
ViewBag.IMAGEPATH = path;
}
return RedirectToAction("Create");
}
There is a view (with buttons for adding):
#using (Html.BeginForm("FileUpload", "ClientsController", FormMethod.Post,
new { enctype = "multipart/form-data", id = Model.СlientIdentificator }))
{
<label for="file">Upload Image:</label>
<input type="file" name="file" id="file" style="width: 100%;" />
<input type="submit" value="Upload" class="submit" />
}
But then I'm trying to upload an image there is no any result (image doesn't upload) or there is an exception targeted to id = Model.ClientIdentificator:
http://i.stack.imgur.com/zqA4y.png
As a result, I'm really want to ask you for universal method to upload an image for client, using controller's method with two arguments HttpPostedFile file and Guid cliendId or a method that is compatible for my task.
P.S. I'll be extremely thankful
P.P.S. Sorry for my English skills :3)

Upload file with input type file in form and c# HttpPostedFile

I try to user an input type file to upload a file but my code don't work.
the variable "filePosted" stay to null value.
My code :
HTML :
<form method="post" name="gestionmembre" runat="server" enctype="multipart/form-data">
#using (Html.BeginForm()){
<label class="lmembre" for="nom">Nom:</label>#Html.TextBox("nom")<br />
<label class="lmembre" for="prenom">Prénom:</label>#Html.TextBox("prenom", Request["Prenom"])<br />
<label class="lmembre" for="mail">Mail:</label>#Html.TextBox("mail", Request["mail"])<br />
<label class="lmembre" for="photo">Photo:</label><input id="phototelecharge" type="file" name="photo" value="Télécharger photo"/> <br />
<div class="errorform">#Html.ValidationSummary()</div>
<input id="ajoutmembre" type="submit" name="boutonmembre" value="Ajouter"/>
}
</form>
I don't know if I have to put this atributes in form tag (method runat enctype).
now, in the controler, in block to receive form values, I put :
else if (Request["boutonmembre"] == "Ajouter")
{
//Traitement de l'upload de l'image
HttpPostedFile filePosted;
filePosted = System.Web.HttpContext.Current.Request.Files["phototelecharge"];
if (filePosted != null && filePosted.ContentLength > 0)
{
string fileNameApplication = System.IO.Path.GetFileName(filePosted.FileName);
string fileExtensionApplication = System.IO.Path.GetExtension(fileNameApplication);
// generating a random guid for a new file at server for the uploaded file
string newFile = Guid.NewGuid().ToString() + fileExtensionApplication;
// getting a valid server path to save
string filePath = System.IO.Path.Combine(Server.MapPath("uploads"), newFile);
if (fileNameApplication != String.Empty)
{
filePosted.SaveAs(filePath);
}
}
}
The problem is in :
filePosted = System.Web.HttpContext.Current.Request.Files["phototelecharge"];
The variable fileposted is null.
In the webpage, I select a file fro a disk and the path of the file is realy indicate in the textbox.
Tks for help me.
David
Here is a simple example
Controller
namespace stackoverflow.Controllers
{
public class HomeController : Controller
{
public ActionResult PostFile(HttpPostedFileBase myFile)
{
System.Diagnostics.Debugger.Break();
return View();
}
}
}
View
#using (Html.BeginForm("PostFile", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div id="postdata">
<input type="file" name="myfile" id="myFile" />
<input type="submit" value="submit" />
</div>
}

FileUpload: keep filenames when showing validation errors

I have the following file-upload code in C# using Asp.Net MVC. The problem is that when validation errors are shown, all the files chosen by the user are lost (input boxes are cleared). Is it possible to keep the input filenames in their original ordering without using javascript? What's the simplest approach?
Controller code
[HttpPost]
public ActionResult Index(IEnumerable<HttpPostedFileBase> files)
{
//check for errors: if errors, ModelState.AddModelError(...);
if (!ModelState.IsValid) {
return View(files);
}
else {
//..........
}
}
View snippet
#using (Html.BeginForm("Index", "Uploader", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
<input type="file" name="files" id="file1" />
#Html.ValidationMessage("1")
</div>
<div class="form-group">
<input type="file" name="files" id="file2" />
#Html.ValidationMessage("2")
</div>
//and 2 more file input fields
<div>
<input type="submit" value="Upload Files" class="btn btn-success btn-lg" />
</div>
}
In postback you can not retain same local path which will remain in type="file".
to do this think there are two way
1) in your current code if you find any file attached then save on server and maintain some flag in hidden field and hide/show your file control with text box( having only filename)
and send it back to browser. Then on next valid submit take that file name that you have already saved. and do your process.
2) On submit of form, copy(DOM copy) all your html control(file ,textbox, hidenfield ect..) in one iframe and submit that iframe.
In case anybody is still in search of a possibility, here is the work around that worked for me. I'm using MVC5. The idea is to use a session variable. I got the idea from ASP.Net Form.
My Model/ViewModel (only relevant properties):
public partial class emp_leaves
{
public string fileNameOrig { get; set; }
public byte[] fileContent { get; set; }
public HttpPostedFileBase uploadFile { get; set; }
}
In my controller (HttpPost):
//Check
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(emp_leaves emp_leaves)
{
if (emp_leaves.uploadFile != null && emp_leaves.uploadFile.ContentLength>0 && !string.IsNullOrEmpty(emp_leaves.uploadFile.FileName))
{
emp_leaves.fileNameOrig = Path.GetFileName(emp_leaves.uploadFile.FileName);
emp_leaves.fileContent = new byte[emp_leaves.uploadFile.ContentLength];
emp_leaves.uploadFile.InputStream.Read(emp_leaves.fileContent, 0, emp_leaves.uploadFile.ContentLength);
Session["emp_leaves.uploadFile"] = emp_leaves.uploadFile; //saving the file in session variable here
}
else if (Session["emp_leaves.uploadFile"] != null)
{//if re-submitting after a failed validation you will reach here.
emp_leaves.uploadFile = (HttpPostedFileBase)Session["emp_leaves.uploadFile"];
if (emp_leaves.uploadFile != null && emp_leaves.uploadFile.ContentLength>0 && !string.IsNullOrEmpty(emp_leaves.uploadFile.FileName))
{
emp_leaves.fileNameOrig = Path.GetFileName(emp_leaves.uploadFile.FileName);
emp_leaves.uploadFile.InputStream.Position = 0;
emp_leaves.fileContent = new byte[emp_leaves.uploadFile.ContentLength];
emp_leaves.uploadFile.InputStream.Read(emp_leaves.fileContent, 0, emp_leaves.uploadFile.ContentLength);
}
}
//code to save follows here...
}
Finally within my edit view: here, i am conditionally showing the file upload control.
< script type = "text/javascript" >
$("#removefile").on("click", function(e) {
if (!confirm('Delete File?')) {
e.preventDefault();
return false;
}
$('#fileNameOrig').val('');
//toggle visibility for concerned div
$('#downloadlrfdiv').hide();
$('#uploadlrfdiv').show();
return false;
}); <
/script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
#model PPMSWEB.Models.emp_leaves #{ HttpPostedFileBase uploadFileSession = Session["emp_leaves.uploadFile"] == null ? null : (HttpPostedFileBase)Session["emp_leaves.uploadFile"]; } #using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data"
})) { #Html.AntiForgeryToken()
<div class="row">
#*irrelevant content removed*#
<div id="downloadlrfdiv" #((!String.IsNullOrEmpty(Model.fileNameOrig) && (Model.uploadFile==n ull || uploadFileSession !=null)) ? "" : "style=display:none;")>
<label>Attachment</label>
<span>
<strong>
<a id="downloadlrf" href="#(uploadFileSession != null? "" : Url.Action("DownloadLRF", "emp_leaves", new { empLeaveId = Model.ID }))" class="text-primary ui-button-text-icon-primary" title="Download attached file">
#Model.fileNameOrig
</a>
</strong>
#if (isEditable && !Model.readonlyMode)
{
#Html.Raw("&nbsp");
<a id="removefile" class="btn text-danger lead">
<strong title="Delete File" class="glyphicon glyphicon-minus-sign"> </strong>
</a>
}
</span>
</div>
<div id="uploadlrfdiv" #(!(!String.IsNullOrEmpty(Model.fileNameOrig) && Model.uploadFile==n ull) && !Model.readonlyMode ? "" : "style=display:none;")>
<label>Upload File</label> #Html.TextBoxFor(model => model.uploadFile, new { #type = "file", #class = "btn btn-default", #title = "Upload file (max 300 KB)" }) #Html.ValidationMessageFor(x => x.uploadFile)
</div>
</div>
}

how to send uploaded file from javascript to controller in MVC?

In my MVC, i have a view and that contains one file upload control and one button.
<input type="file" id="Uploadfile" />
<input type="button" onclick()="GetFile();/>
Javascript function as follows
function GetFile()
{
var file_data = $("#Uploadfile").prop("files")[0];
window.location.href="Calculation/Final?files="+file_data;
}
I need to pass/send the selected file via fileupload control to controller in mvc.
i have the controller
public ActionResult Final(HttpPostedFileBase files)
{
//here i have got the files value is null.
}
How to get the selected file and send it to the controller?
Plz help me to fix this issue.
I had similar functionality to deliver in my project.
The working code looks something like this:
Controller Class
[HttpPost]
public ActionResult UploadFile(YourModel model1)
{
foreach (string file in Request.Files)
{
HttpPostedFileBase hpf = Request.Files[file] as HttpPostedFileBase;
if (hpf.ContentLength > 0)
{
string folderPath = Server.MapPath("~/ServerFolderPath");
Directory.CreateDirectory(folderPath);
string savedFileName = Server.MapPath("~/ServerFolderPath/" + hpf.FileName);
hpf.SaveAs(savedFileName);
return Content("File Uploaded Successfully");
}
else
{
return Content("Invalid File");
}
model1.Image = "~/ServerFolderPath/" + hpf.FileName;
}
//Refactor the code as per your need
return View();
}
View
#using (#Html.BeginForm("UploadFile", "Upload", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<table style="border: solid thin; margin: 10px 10px 10px 10px">
<tr style="margin-top: 10px">
<td>
#Html.Label("Select a File to Upload")
<br />
<br />
<input type="file" name="myfile">
<input type="submit" value="Upload" />
</td>
</tr>
</table>
}
you cannot send file content via javascript (unless HTMl5). and you are doing totally wrong. if you want to do HTML5 based solution via FileReader api then you need to check this out. FileReader Api
Just put a form tag and use the same name of the input in the controller action to perform model binding
#using(Html.BeginForm("yourAction","YourControl",FormMethod.Post))
{
<input type="file" id="fileUpload" />
}
then in controller.
[HTTPPost]
public ActionResult Final(HttpPostedFileBase fileUpload)
{
//here i have got the files value is null.
}
Below code will do a full post back in an hidden form which will give an illusion of ajax file upload. Try it:
Update:
JS
function Upload(sender) {
var iframe = $("<iframe>").hide();
var newForm = $("<FORM>");
newForm.attr({ method: "POST", enctype: "multipart/form-data", action: "/ControllerName/Final" });
var $this = $(sender), $clone = $this.clone();
$this.after($clone).appendTo($(newForm));
iframe.appendTo($("html")).contents().find('body').html($(newForm));
newForm.submit();
}
HTML
<input type="file" id="Uploadfile" name="Uploadfile" />
<input type="button" onclick="Upload($('#UploadFile'));"/>
Controller
public ActionResult Final(HttpPostedFileBase Uploadfile)
{
//here you can use uploaded file
}
As a completion from Ravi's answer, I would suggest to use the following using statement:
#using(Html.BeginForm("yourAction","YourControl",FormMethod.Post, new { enctype="multipart/form-data" }))
{
<input type="file" id="fileUpload" />
}
You can do it by using json data to view.
As instance,
Controller
public ActionResult Products(string categoryid)
{
List<catProducts> lst = bindProducts(categoryid);
return View(lst);
}
public JsonResult Productsview(string categoryid)
{
//write your logic
var Data = new { ok = true, catid = categoryid};
return Json(Data, JsonRequestBehavior.AllowGet);
}
View:
#{
ViewBag.Title = "Index";
}
#model ASP.NETMVC.Controllers.Categories
<h2>List Of Categories</h2>
#Html.ListBox("lst_categories", (IEnumerable<SelectListItem>) ViewBag.Categories)
<script type="text/javascript">
$(function () {
$('#lst_categories').change(function () {
var catid = $('#lst_categories :selected').val();
$.ajax({
url: '#Url.Action("Productsview", "Jquery")',
type: 'GET',
dataType: 'json',
data: { categoryid: catid },
cache: false,
success: function (Data) {
if (Data.ok) {
var link = "#Url.Action("Products", "Jquery", new { categoryid = "catid" })";
link = link.replace("catid", Data.catid);
alert(link);
window.location.href = link;
}
}
});
});
});
</script>

Categories

Resources