I have the following code which works with input type file, I did some changes by replacing the input type file with filepond plugin. I am unable to post it to controller. Is it possible to add a new object to FormData?
I have my model as follows
public class ReportableEventModel
{
public string IMONumber { get; set; }
public string VesselName { get; set; }
public List<HttpPostedFileBase> Documents { get; set; }
}
This is my view
using (Html.BeginForm("ReportablEventUpdate", "Reportable", FormMethod.Post, new { #id = "EventEdit", ReportableEventId = Model.ReportableEvent.ReportableEventId, enctype = "multipart/form-data" }))
{
<input type="number" class="form-control" id="IMONumber" name="IMONumber" required placeholder="Enter IMO No" value="#Model.IMONumber" onkeydown="return event.keyCode !== 69" maxlength="7" oninput="javascript: if (this.value.length > this.maxLength) this.value = this.value.slice(0, this.maxLength);">
<input type="text" class="form-control" id="VesselName" name="VesselName" required placeholder="Enter Vessel Name" value="#Model.VesselName">
<input type="file" class="filepond adminPond" name="Documents" multiple />
<button class="btn btn-primary" id="btn-submit1" type="submit" onclick="return validateSubmit();">Save</button>
}
This is how I am changing the file to filepond
<script type="text/javascript">
var adminPond;
var adminFileNames = [];
FilePond.registerPlugin(
FilePondPluginFileEncode,
FilePondPluginImageExifOrientation
);
adminPond = FilePond.create(
document.querySelector(
'input.adminPond'));
adminPond.on('addfile', function (error, file) {
if (adminFileNames.includes(file.filename)) {
var fileError = "A file with name " + file.filename + " was already uploaded";
createToast("Error", fileError, TOAST_STATUS.DANGER);
handleFileError(file, adminPond);
}
adminFileNames.push(file.filename);
});
adminPond.on('removefile', function (err, f) {
adminFileNames = [];
var fileCnt = adminPond.getFiles().length;
for (var fCnt = 0; fCnt < fileCnt; fCnt++) {
var file = adminPond.getFile(fCnt);
adminFileNames.push(file.filename);
}
});
On submit I am trying as follows to append the uploaded files but not working,
function validateSubmit() {
var data = new FormData($("#EventEdit")[0]);
let files = adminPond.getFiles().length;
for (let i = 0; i < files; i++) {
data.append(`Document[${i}]`, adminPond.getFile(i).file);
}
showSpinner();
return true;
}
So can some one let me know how can I pass an item to the form using FormData, here is the jquery fiddle of file pond I am using
https://jsfiddle.net/DorababuMeka/ydj2aruL/
Related
So I'm trying to build an virtual file storage, im stuck at the part where I have to upload files and after that display them in a File-s view so that the user can download, delete or see them. The form input together with the file upload is in a modal box. To process the modal form I have used #Html.BeginForm and to process the file upload I have used ajax. What I have achieved until now is that I can upload the files to the server folder, but I dont konw how I can save the file name and the file path to the database of file-s table. And I also need help on how to display these files in a specific view. Thank you in advance.
Html
<div class="modal-body">
#using (Html.BeginForm("SaveRecord", "NgarkoDokument", FormMethod.Post, new { enctype = "mulptiple/form-data" }))
{
<div class="form-group">
<label for="exampleFormControlSelect1">Lloji i dokumentit</label><br />
<select title="Lloji i dokumentit" name="lloji" class="form-control col-md-3 box" id="tipiDropdown"> </select>
<input type="button" title="Ngarko dokument" name="ngarko" value="Ngarko" id="uploadPop" class="btn btn-info col-md-3" onclick="document.getElementById('file').click();" />
<input type="file" onchange="javascript: updateList()" multiple="multiple" style="display:none;" id="file" name="postedFiles"/>
<div id="fileList"></div>
</div>
<br /><br />
<div class="form-group">
<label for="formGroupExampleInput">Fusha indeksimi</label> <br />
#*<input title="Indeksimi dokumentit" id="indeksimi" class="form-control col-md-3" type="text" name="indeksimi" placeholder="indeksimi" required />*#
#Html.TextBoxFor(a => a.Fusha_Indeksimit.Emri_Indeksimit, new { #class = "form-control", #placeholder = "indeksimi" })
#* <button title="Shto indeksim" id="modalPlus" type="submit" class="btn btn-info"><i class="glyphicon glyphicon-plus"></i></button>*#
</div>
<label for="formGroupExampleInput">Vendndodhja fizike e dokumentit</label><br>
<div id="zyraModal" class="form-group col-md-4">
#*<input title="Zyra fizike" id="zyra" class="form-control" type="text" name="zyra" placeholder="Zyra" />*#
#Html.TextBoxFor(a => a.Vendndodhja_fizike.Zyra, new { #class = "form-control", #placeholder
= "Zyra" })
</div>
<div class="form-group col-md-4">
#* <input title="Kutia fizike" id="kutia" class="form-control" type="number" name="kutia" placeholder="Nr i kutisë" />*#
#Html.TextBoxFor(a => a.Vendndodhja_fizike.Nr_Kutise, new { #class = "form-control", #placeholder = "Nr i kutisë" })
</div>
<div class="form-group col-md-4">
#* <input title="Rafti fizik" id="rafti" class="form-control" type="text" name="rafti" placeholder="Rafti" />*#
#Html.TextBoxFor(a => a.Vendndodhja_fizike.Rafti, new { #class = "form-control", #placeholder = "Rafti" })
</div>
<br /><br />
<div class="row" id="ruaj">
<button title="Ruaj dokumentin" type="submit" class="btn btn-success">Ruaj</button>
</div>
}
</div>
Ajax script
<script type="text/javascript">
$(document).ready(function () {
$("#file").change(function () {
console.log("Image selected!");
var formData = new FormData();
var totalFiles = document.getElementById("file").files.length;
for (var i = 0; i < totalFiles; i++) {
var file = document.getElementById("file").files[i];
formData.append("file", file);
}
$.ajax({
type: "POST",
url: '/UploadFile/Upload',
data: formData,
dataType: 'json',
contentType: false,
processData: false,
success: function (response) {
alert('succes!!');
}
});
});
});
</script>
Controller
public ActionResult Dokument()
{
return View();
}
[HttpPost]
public void Upload()
{
Dokumenti dok = new Dokumenti();
for (int i = 0; i < Request.Files.Count; i++)
{
var file = Request.Files[i];
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/File/"), fileName);
file.SaveAs(path);
}
}
public ActionResult SaveRecord(NgarkoDokument model)
{
try
{
Vendndodhja_Fizike vendndodhja = new Vendndodhja_Fizike();
vendndodhja.Zyra = model.Vendndodhja_fizike.Zyra;
vendndodhja.Rafti = model.Vendndodhja_fizike.Rafti;
vendndodhja.Nr_Kutise = model.Vendndodhja_fizike.Nr_Kutise;
db.Vendndodhja_Fizike.Add(vendndodhja);
Fusha_Indeksimit indeksimi = new Fusha_Indeksimit();
indeksimi.Emri_Indeksimit = model.Fusha_Indeksimit.Emri_Indeksimit;
db.Fusha_Indeksimit.Add(indeksimi);
Dokumenti dok = new Dokumenti();
dok.Emer = model.Dokumenti.Emer;
db.Dokumenti.Add(dok);
db.SaveChanges();
//int lastUserId = dok.UserID;
}
catch(Exception ex)
{
throw ex;
}
return RedirectToAction("Dokument");
}
}
First of all, you may need to specify this because you send FormData to your controller. For example:
public async Task CreateAsync([FromForm] CreateBookDto input)
{
...
}
I care about a lot of things while uploading the file so my js file is a bit long but you can get what works for you:
$(function () {
var fileInput = document.getElementById('Book_CoverImageFile');
var file;
fileInput.addEventListener('change', function () {
var showModal = true;
file = fileInput.files[0];
document.getElementById("choose-cover-image").innerHTML = file.name;
var permittedExtensions = ["jpg", "jpeg", "png"]
var fileExtension = $(this).val().split('.').pop();
if (permittedExtensions.indexOf(fileExtension) === -1) {
showModal = false;
alert('This extension is not allowed')
$('#Book_CoverImageFile').val('');
$("#choose-cover-image").html("Choose a cover image...");
}
else if(file.size > 5*1024*1024) {
showModal = false;
alert('The file is too large');
}
var img = new Image();
img.onload = function() {
var sizes = {
width:this.width,
height: this.height
};
URL.revokeObjectURL(this.src);
if (sizes.width > 1920 && sizes.height > 1080){
alert('Height and Width must not exceed 1920*1080.')
$('#Book_CoverImageFile').val('');
$("#choose-cover-image").html("Choose a cover image...");
}
var aspectRatio = sizes.width / sizes.height;
aspectRatio = Number (aspectRatio.toFixed(1));
if (aspectRatio !== 1.8){
alert("The picture you uploaded is not in 16:9 aspect ratio!")
$('#Book_CoverImageFile').val('');
$("#choose-cover-image").html("Choose a cover image...");
}
}
if(showModal === true) {
readURL(this);
$('#myModal').modal('show');
}
var objectURL = URL.createObjectURL(file);
img.src = objectURL;
});
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#img-upload').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
$('form#CreateBookForm').submit(function (e) {
e.preventDefault();
var title = $('#Book_Title').val().trim();
var formData = new FormData();
formData.append("Title", title);
formData.append("CoverImageFile", file);
$.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener("progress", function(evt) {
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
percentComplete = parseInt(percentComplete * 100);
if(percentComplete !== 100){
$( '#Book_CoverImageFile' ).prop( "disabled", true );
$( '#Book_Title' ).prop( "disabled", true );
$( '#btnSubmit' ).prop( "disabled", true );
}
}
}, false);
return xhr;
},
url: app.appPath + `api/app/Book`,
data: formData,
type: 'POST',
contentType: false,
processData: false,
success: function(data){
alert("The Book has been successfully submitted. It will be published after a review from the site admin.");
window.location.href = "/books";
},
error: function (data) {
alert(data.responseJSON.error.message);
}
});
});
This does many things, for example; file permitted extension control, control of file size, checking whether the file is more than 1920 * 1080 pixels, whether the file has 16:9 aspect ratio, disabling form elements while sending the file, etc...
And if you really care about security, you should;
To only accept permitted extensions:
public class AllowedExtensionsAttribute : ValidationAttribute
{
private readonly string[] _extensions;
public AllowedExtensionsAttribute(string[] extensions)
{
_extensions = extensions;
}
protected override ValidationResult IsValid(
object value, ValidationContext validationContext)
{
if (value == null) // If uploading a file is optional on the form screen, it should be added == CanBeNul
{
return ValidationResult.Success;
}
var file = value as IFormFile;
var extension = Path.GetExtension(file.FileName);
if (file.Length > 0 && file != null)
{
if (!_extensions.Contains(extension.ToLower()))
{
return new ValidationResult(GetErrorMessage());
}
}
return ValidationResult.Success;
}
public string GetErrorMessage()
{
return $"This extension is not allowed!";
}
}
To limit the uploaded file size:
public class MaxFileSizeAttribute : ValidationAttribute
{
private readonly int _maxFileSize;
public MaxFileSizeAttribute(int maxFileSize)
{
_maxFileSize = maxFileSize;
}
protected override ValidationResult IsValid(
object value, ValidationContext validationContext)
{
if (value == null) // If uploading a file is optional on the form screen, it should be added == CanBeNull
{
return ValidationResult.Success;
}
var file = value as IFormFile;
if (file.Length > 0)
{
if (file.Length > _maxFileSize)
{
return new ValidationResult(GetErrorMessage());
}
}
return ValidationResult.Success;
}
public string GetErrorMessage()
{
return $"Maximum allowed file size is { _maxFileSize} bytes.";
}
}
And you must add them to Dto:
public class CreateBookDto
{
[Required]
[StringLength(64)]
public string Title { get; set; }
[CanBeNull]
[DataType(DataType.Upload)]
[MaxFileSize(5*1024*1024)] // 5mb
[AllowedExtensions(new string[] { ".jpg", ".png", ".jpeg" })]
public IFormFile CoverImageFile { get; set; }
}
Finally, your HTML file should look like this:
<form method="post" id="CreateBookForm" asp-page="/Book/Create" enctype="multipart/form-data">
<div class="form-group">
<div class="custom-file">
<input asp-for="Book.CoverImageFile" type="file" name="file" class="custom-file-input" id="Book_CoverImageFile"
required="required">
<label id="choose-cover-image" class="custom-file-label" for="customFile">Choose a cover image...</label>
<small class="form-text text-muted">#L["CreateBookCoverInfo"].Value</small>
</div>
</div>
...
<button id="btnSubmit" type="submit" class="btn btn-primary btn-block">Submit</button>
</form>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<img class="img-fluid" id="img-upload" alt=""/>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary btn-block" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
Conceptual question about how Angular.js works with my Web API to fetch data and update view
I'm new to Web development and I'm trying to solidify my concepts, so this is more of a theoretical question thaa a programming one. I implemented a ASP.net Web App with a Web API to fetch data from a database and used Angular.js for the front-end UI. My application is a simple database consisting of students and their info. All I'm doing is displaying the info using Angular.js and Web API. This question is about how the flow actually works to update the data in the database after a user submits a form on the UI.
Steps:
User clicks on the save button on the Student page after filling out the form.
This save button which has a ng-click() event handler associated with it will now go to the associated controller which is StudentCtrl.js. StudentCtrl.js has the CrudService as a dependency as well as some $scope variables
Now the data binding happens in the .SaveUpdate() function to bind whatever was submitted in the textbox into the dataModel which is 'student' in this case.
After this, a base url + apiRoute is used to make an HttpPost request.
The HttpPost request is made to CrudService.js so that it can pass this data to the server to save it.
The CrudService.js will now trigger the correct http method. In this case, it calls the post() method passing the route and the dataModel containing the data.
StudentApiController.cs now receives a request to do a post() action by CrudService.js which awaits a response from it.
StudentApiController will now use its save method and manipulate the data using the dbContext
Once the StudentAPIController is done, it returns a response back with HttpStatusMesssage to CrudService.js
CrudService.js now returns a response to StudentCtrl.js which checks if the response is acceptable and presents a new view to the user which shows the newly added student.
Questions:
Is this how the flow actually works from the time the user hits the save button to when it is actually saved in the database?
How does the dbContext end up manipulating the data? Does it cause some SQL queries to be created? I remember reading something about this because Entity framework creates SQL statements to do the actual updating.
There is a StudentController.cs file which returns View(). Where does this come in in the process I explained above?
index.cshtml:
<form novalidate name="frmStudent" id="frmStudent" class="form-horizontal row-border">
<br />
<div class="col-md-12">
<div class="form-group">
<label class="col-md-4 control-label" for="input17"> First Name</label>
<div class="col-md-7">
<input type="text"
id="idFirstName"
class="form-control"
name="nameFirstName" ng-model="firstName" />
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label" for="input17"> Last Name</label>
<div class="col-md-7">
<input type="text"
id="idLastName"
class="form-control"
name="nameFirstName" ng-model="lasttName" />
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label" for="input17"> Email</label>
<div class="col-md-7">
<input type="text"
id="idEmail"
class="form-control"
name="nameEmail" ng-model="email" />
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label" for="input17"> Address</label>
<div class="col-md-7">
<input type="text"
id="idAddress"
class="form-control"
name="nameAdress" ng-model="address" />
</div>
</div>
<div class="form-group">
<div class="col-md-4">
</div>
<div class="col-md-7">
<span id="save" class="btn btn-success margin-right-btn"
ng-click="SaveUpdate()">
<i class="icon-save"></i> {{btnText}}
</span>
</div>
</div>
</div>
</form>
StudentCtrl.js:
app.controller('StudentCtrl', ['$scope', 'CrudService',
function ($scope, CrudService) {
// Base Url
var baseUrl = '/api/StudentAPI/';
$scope.btnText = "Save";
$scope.studentID = 0;
$scope.SaveUpdate = function () {
var student = {
FirstName: $scope.firstName,
LastName: $scope.lasttName,
Email: $scope.email,
Address: $scope.address,
StudentID: $scope.studentID
}
if ($scope.btnText == "Save") {
var apiRoute = baseUrl + 'SaveStudent/';
var saveStudent = CrudService.post(apiRoute, student);
saveStudent.then(function (response) {
if (response.data != "") {
alert("Data Saved Successfully");
$scope.GetStudents();
$scope.Clear();
} else {
alert("Some error");
}
}, function (error) {
console.log("Error: " + error);
});
}
else {
var apiRoute = baseUrl + 'UpdateStudent/';
var UpdateStudent = CrudService.put(apiRoute, student);
UpdateStudent.then(function (response) {
if (response.data != "") {
alert("Data Updated Successfully");
$scope.GetStudents();
$scope.Clear();
} else {
alert("Some error");
}
}, function (error) {
console.log("Error: " + error);
});
}
}
$scope.Clear = function () {
$scope.studentID = 0;
$scope.firstName = "";
$scope.lasttName = "";
$scope.email = "";
$scope.address = "";
}
$scope.GetStudents = function () {
var apiRoute = baseUrl + 'GetStudents/';
var student = CrudService.getAll(apiRoute);
student.then(function (response) {
$scope.students = response.data;
},
function (error) {
console.log("Error: " + error);
});
}
$scope.GetStudents();
CrudService.js
app.service('CrudService', function ($http) {
var urlGet = '';
this.post = function (apiRoute, Model) {
var request = $http({
method: "post",
url: apiRoute,
data: Model
});
return request;
}
this.put = function (apiRoute, Model) {
var request = $http({
method: "put",
url: apiRoute,
data: Model
});
return request;
}
this.delete = function (apiRoute) {
var request = $http({
method: "delete",
url: apiRoute
});
return request;
}
this.getAll = function (apiRoute) {
urlGet = apiRoute;
return $http.get(urlGet);
}
this.getbyID = function (apiRoute, studentID) {
urlGet = apiRoute + '/' + studentID;
return $http.get(urlGet);
}
});
StudentAPIController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;
using System.Data.Entity;
using CRUDOperations.Models;
namespace CRUDOperations.api
{
[RoutePrefix("api/StudentAPI")]
public class StudentAPIController : ApiController
{
StudentDBEntities dbContext = null;
public StudentAPIController() {
dbContext = new StudentDBEntities();
}
[ResponseType(typeof(tblStudent))]
[HttpPost]
//Saves a particular student in the database
public HttpResponseMessage SaveStudent(tblStudent astudent) {
int result = 0;
try
{
dbContext.tblStudents.Add(astudent);
dbContext.SaveChanges();
result = 1;
}
catch (Exception e) {
result = 0;
}
return Request.CreateResponse(HttpStatusCode.OK, result);
}
//Gets all the students from the database:
[ResponseType(typeof(tblStudent))]
[HttpGet]
public List<tblStudent> GetStudents() {
List<tblStudent> students = null;
try {
students = dbContext.tblStudents.ToList();
} catch (Exception e) {
students = null;
}
return students;
}
//For eg a complete route will be: /api/StudentAPI/GetStudentByID/2
//Edit the student data:
//Constraint that the studentID needs to be an int
[Route("GetStudentByID/{studentID:int}")]
[ResponseType(typeof(tblStudent))]
[HttpGet]
public tblStudent GetStudentByID(int studentID)
{
tblStudent astudent = null;
try
{
astudent = dbContext.tblStudents.Where(x => x.StudentID == studentID).SingleOrDefault();
}
catch (Exception e)
{
astudent = null;
}
return astudent;
}
//Updating the student details:
[ResponseType(typeof(tblStudent))]
[HttpPut]
public HttpResponseMessage UpdateStudent(tblStudent astudent) {
int result = 0;
try {
dbContext.tblStudents.Attach(astudent);
dbContext.Entry(astudent).State = EntityState.Modified;
dbContext.SaveChanges();
result = 1;
} catch {
result = 0;
}
return Request.CreateResponse(HttpStatusCode.OK,result);
}
//Delete the student:
[Route("DeleteStudent/{studentID:int}")]
[ResponseType(typeof(tblStudent))]
[HttpDelete]
public HttpResponseMessage DeleteStudent(int studentID) {
int result = 0;
try {
var student = dbContext.tblStudents.Where(x => x.StudentID == studentID).FirstOrDefault();
//Attach lets us update only that entity, not every field in the table.
dbContext.tblStudents.Attach(student);
dbContext.tblStudents.Remove(student);
dbContext.SaveChanges();
result = 1;
} catch (Exception e) {
result = 0;
}
return Request.CreateResponse(HttpStatusCode.OK, result);
}
}
}
StudentController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace CRUDOperations.Controllers
{
public class StudentController : Controller
{
// GET: Student
public ActionResult Index()
{
return View();
}
public ActionResult viewAllStudents() {
return View();
}
}
}
As a newbie in ASP.NET Core, this is my first time trying to make an ajax call to asp.net controller method with jquery and I am finding it difficult. Below is my view form, my javascript file and my controller method;
The view form
<form id="components-form">
#Html.AntiForgeryToken();
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="entryformLabel">Payment Entries</h4>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped" id="list-table">
<thead>
<tr>
<th>Entry</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
#foreach (var ent in ViewBag.staffEntries)
{
<tr>
<th>#ent.EntryLabel</th>
<th><input type="text" class="form-control entry" name="component[#ent.EntryId]" id="#ent.EntryId" value="#ent.EntryValue" /></th>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" id="update-entries-btn" class="btn btn-success"><span class="fa fa-check"></span> Update Entries</button>
</div>
</form>
The Javascript file
$(document).ready(function ()
{
var updateBtn = $("#update-entries-btn").click(function ()
{
$("#update-entries-btn").click(function () {
var token = $("[name=__RequestVerificationToken").val();
var postedValues = new FormData();
postedValues.append("__RequestVerificationToken", token);
$(".entry").each(function () {
var id = this.id;
var val = this.val;
postedValues.append(id,val);
});
var postUrl = "/staff/updatecomponents";
$.post(postUrl, postedValues, function (result) {
alert(result);
});
})
})
}
);
The controller method. I'm actually lost on how to handle the request at this point. Doint this returns null.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult updatecomponents(string posted)
{
return Json(posted);
}
I will appreciate a guide to get this working.
Thank you
After some more research, I solved this thus:
The Javascript code
$(document).ready(function ()
{
$("#update-components-btn").click(function ()
{
var token = $("[name=__RequestVerificationToken").val();
var staffId = $("[name=staffId").val();
var postedValues = {};
postedValues["__RequestVerificationToken"] = token;
postedValues.StaffId = staffId;
postedValues.StaffComponents = [];
$(".entry").each(function ()
{
var component = {};
component.StaffId = staffId;
component.EntryId = $(this).attr('id');
component.ValueAmount = Number($(this).val());
postedValues.StaffComponents.push(component);
});
var postUrl = "/staff/updatecomponents";
$.post(postUrl, postedValues, function (result)
{
var report = JSON.parse(JSON.stringify(result));
if (report.status)
{
swal("<span class=fa fa-thumbs-up", report.message, "success");
setInterval(function () { window.location.reload(true); }, 5000);
}
else
{
swal("<span class=fa fa-thumbs-down", report.message, "error");
}
});
});
}
);
I had to create a model that would emulate the expected object
public class StaffEntryUpdateModel
{
public string RequestToken { get; set; }
public string StaffId { get; set; }
public List<StaffEntry> StaffComponents { get; set; }
}
And finally the server side endpoint that receives and processes the ajax post
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult updatecomponents(StaffEntryUpdateModel postedData)
{
try
{
if (postedData.StaffComponents.Any())
{
ApplicationUser Staff = db.Users.FirstOrDefault(s => s.Id == postedData.StaffId);
if (Staff == null)
{
return new JsonResult(new { Status = false, Message = "Unknown staff" });
}
db.StaffEntries.Where(se => se.StaffId == postedData.StaffId).Delete();
foreach (var c in postedData.StaffComponents)
{
db.StaffEntries.Add(c);
}
int inserted = db.SaveChanges();
return new JsonResult(new { Status = (inserted > 0) ? true : false, Message = inserted + " components updated for staff" });
}
else
{
return new JsonResult(new { Status = false, Message = "No component sent for update for staff" });
}
}
catch (Exception e)
{
return new JsonResult(new {Status=false,Message=e.Message.ToString() });
}
}
In the process of working and reviewing the code, I had to change some items from the way it appeared in the original question but its basically the same.
I hope this helps someone looking for such solution anytime.
Thank you #Chetan Ranpariya for your attempt to help
This is my View
Test Upload File
<form action="#Url.Action("Index", "Home")" method="post" enctype="multipart/form-data">
#Html.AntiForgeryToken()
<label for="file">Filename:</label>
<input type="file" name="files" id="files" />
<input type="submit" name="submit" value="Upload" />
</form>
This is my Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(IEnumerable<HttpPostedFileBase> files)
{
if (files != null)
{
foreach (var file in files)
{
try
{
if (file != null && file.ContentLength > 0)
{
var fileName = file.FileName;
var path = Path.Combine(Server.MapPath(#"\Upload"), fileName);
file.SaveAs(path);
ViewBag.Message = "File uploaded successfully";
}
}
catch (Exception ex)
{
ViewBag.Message = "ERROR:" + ex.Message.ToString();
}
}
}
return View();
}
The problem is the HttpPostedFileBase files is always null. I cant find the problem.
Here is an example how to use form onsubmit method
Your HTML part
<form id="formTest" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="files" id="files" />
<input type="submit" name="submit" value="Upload" />
</form>
script
<script type="text/javascript">
var form = document.getElementById('formTest').onsubmit = function (e) {
e.preventDefault();
var formdata = new FormData(); //FormData object
var fileInput = document.getElementById('files');
if (fileInput != "" && fileInput.files.length > 0) {
//Iterating through each files selected in fileInput
for (i = 0; i < fileInput.files.length; i++) {
//Appending each file to FormData object
formdata.append(fileInput.files[i].name, fileInput.files[i]);
}
//Creating an XMLHttpRequest and sending
var xhr = new XMLHttpRequest();
var url = '#Url.Action("Index","Home")';
xhr.open('POST', url);
xhr.send(formdata);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var result = xhr.responseText;
}
}
return false;
}
}
</script>
C#
public ActionResult Index()
{
if (Request.Files.Count > 0)
{
var file = Request.Files[0];
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/Images/"), fileName);
file.SaveAs(path);
}
return View();
}
}
You can also handle files with Request.Files like this:
public ActionResult Index()
{
if (Request.Files.Count > 0)
{
var file = Request.Files[0];
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/Images/"), fileName);
file.SaveAs(path);
}
}
}
And for your second question, please try to use it between Html.BeginForm instead of form like this:
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<label>Filename:</label>
<input type="file" name="file1"/>
<input type="submit" name="submit" value="Upload" />
}
i am trying to upload files with the jqueryform plugin. I have to file upload controls but the second one cant upload?
<div>
<h2>
Upload test</h2>
<script src="../../Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-ui-1.8.12.custom.min.js" type="text/javascript"></script>
<script src="../../Scripts/jqueryform.js" type="text/javascript"></script>
<script src="../../Scripts/jblock.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function (event) {
$(function () {
$("#ajaxUploadForm").ajaxForm({
iframe: true,
dataType: "json",
beforeSubmit: function () {
$("#ajaxUploadForm").block({ message: ' Uploading Image' });
},
success: function (result) {
$("#ajaxUploadForm").unblock();
$("#ajaxUploadForm").resetForm();
//$.growlUI(null, result.message);
if (result.message != 'Success') {
alert(result.message);
}
else {
}
},
error: function (xhr, textStatus, errorThrown) {
$("#ajaxUploadForm").unblock();
$("#ajaxUploadForm").resetForm();
}
});
});
});
</script>
<form id="ajaxUploadForm" action="<%= Url.Action("Upload", "Home")%>" method="post"
enctype="multipart/form-data">
<input type="file" name="file" />
<input type="file" name="file2" />
<input id="ajaxUploadButton" type="submit" value="upload file" />
</form>
</div>
public ActionResult Index()
{
return View();
}
public FileUploadJsonResult Upload(HttpPostedFileBase file)
{
if (file == null)
{
return new FileUploadJsonResult { Data = new { message = "error" } };
}
if (file.ContentLength > 0)
{
//save file or something
}
return new FileUploadJsonResult { Data = new { message = string.Format("success") } };
}
public class FileUploadJsonResult : JsonResult
{
public override void ExecuteResult(ControllerContext context)
{
this.ContentType = "text/html";
context.HttpContext.Response.Write("<textarea>");
base.ExecuteResult(context);
context.HttpContext.Response.Write("</textarea>");
}
}
You have two file inputs on your form named respectively file and file1. You controller action that handles the upload has only a single HttpPostedFileBase argument named file. So you could add a second one:
public FileUploadJsonResult Upload(
HttpPostedFileBase file,
HttpPostedFileBase file1
)
{
if (file == null || file1 == null)
{
return new FileUploadJsonResult { Data = new { message = "error" } };
}
if (file.ContentLength > 0)
{
//save file or something
}
if (file1.ContentLength > 0)
{
//save the second file or something
}
return new FileUploadJsonResult { Data = new { message = string.Format("success") } };
}
Or if you wanted to handle multiple files you could give them the same name on your form:
<input type="file" name="files" />
<input type="file" name="files" />
<input type="file" name="files" />
<input type="file" name="files" />
<input type="file" name="files" />
...
and your controller action could then take a list of files:
public FileUploadJsonResult Upload(IEnumerable<HttpPostedFileBase> files)
{
if (files)
{
return new FileUploadJsonResult { Data = new { message = "error" } };
}
foreach (var file in files)
{
if (file.ContentLength > 0)
{
//save file or something
}
}
return new FileUploadJsonResult { Data = new { message = string.Format("success") } };
}
You may checkout the following blog post about uploading files in ASP.NET MVC.