POST file list to controller in ajax post - javascript

I tried to upload documents but I couldnt pass to list my controllers parameter. My scenario is:
user click to "choose file" button and pick the files and press done
then my some functions get file list and pass to controller for save locally via POST merhod like below:
view side: (get file list)
function saveDocuments(documentList) {
if (documentList.length > 0)
{
var formList = new Array;
for (var i = 0; i < documentList.length; i++) {
var form = new FormData();
var file = documentList[i];
form.append('FormFile', file);
formList.push(form);
}
savePhysicalFile(formList);
}
}
view side: (post file list)
function savePhysicalFile(formData)
{
if (formData != null)
{
$.ajax({
url: "Installation/SavePhysicalPath",
type: 'POST',
dataType: "json",
contentType: "multipart/form-data",
data:formData,
processData: false,
contentType: false,
success: function (result) {
console.log("Success", result);
},
error: function (data) {
console.log(data);
}
});
}
}
In my controller side; the parameter "model" is always null. I couldnt pass view side list here. How can I figure out ?
controller side
public JsonResult SavePhysicalPath([FromForm] List<FileModel> model)
{
var savingRootPath = #"C:\MyDocuments";
//I'm doing save locally
return Json(savingRootPath);
}
model side
public class FileModel
{
public string Files { get; set; }
public IFormFile FormFile { get; set; }
}

From your code,you may pay attention to two things here:
1.For each property of the complex type, model binding looks through the sources for the name pattern prefix.property_name. If nothing is found, it looks for just property_name without the prefix.For model you receive in backend is a List,you need give the name like:[index].FormFile or model[index].FormFile.
2.Your model has a IFormFile and your action receives a list model,if you only pass the IFormFile you need remove FromForm attribute and be sure do not have [ApiController].It is a known github issue and this has been moved to Next sprint planning milestone.
Here is a whole working demo:
View:
<input type="file" multiple onchange="saveDocuments(this.files)"/>
<div class="form-group">
<input type="button" value="Submit" id="submit" class="btn btn-primary" />
</div>
#section Scripts
{
<script>
function saveDocuments(documentList) {
if (documentList.length > 0) {
var form = new FormData();
for (var i = 0; i < documentList.length; i++) {
var file = documentList[i];
//change here
form.append('model['+i+'].FormFile', file);
}
savePhysicalFile(form);
}
}
function savePhysicalFile(formData) {
if (formData != null) {
$.ajax({
url: "/Installation/SavePhysicalPath",
type: 'POST',
dataType: "json",
contentType: "multipart/form-data",
data: formData,
processData: false,
contentType: false,
success: function (result) {
console.log("Success", result);
},
error: function (data) {
console.log(data);
}
});
}
}
</script>
}
Controller:
[HttpPost]
public JsonResult SavePhysicalPath(List<FileModel> model)
{
var savingRootPath = #"C:\MyDocuments";
//I'm doing save locally
return Json(savingRootPath);
}
Result:

Related

How can I send a viewmodel to controller through Ajax

The user is able to write text and upload a file.
Using Javascript, I create an object with the file and text as properties, then send it to the controller using Ajax.
Using debugging, it seems that the problem is in the Ajax part. Everything before that(file upload, object creation) seems to be fine.
Here is the Javascript/JQuery:
function AddPost() {
var fileInput = document.getElementById('file').files;
var textInput = document.getElementById('addPostText').value;
if (fileInput != null || textInput != null) {
file = null;
if (fileInput.length > 0) {
file = fileInput[length-1];
}
var AddPostViewModel =
{
"Text": textInput,
"File": file
};
$.ajax(
{
url: "#Url.Action('AddPost')",
type: "POST",
dataType: "json",
data: JSON.stringify(AddPostViewModel),
contentType: 'application/json; charset=utf-8'
}
);
}
}
Here is the method in the controller:
[HttpPost]
public void AddPost(AddPostViewModel viewModel)
{
}
And here is the object:
public class AddPostViewModel
{
[DataType(DataType.MultilineText)]
public string Text { get; set; }
public IFormFile File { get; set; }
}
The HTML:
<textarea id="addPostText"></textarea>
<div class="upload-button">
<div class="label">Add image</div>
<input id="file" type="file" size="1" />
</div>
You can't send the File inside a json. Also, you've a bug in line file = fileInput[length-1]; (length is wrong, should be 0 or fileInput.length-1.
Here is a working function. This function should be inside a Razor Page because it needs to build the form action url #Url.Action("AddPost").
function AddPost() {
var fileInput = document.getElementById('file').files;
var textInput = document.getElementById('addPostText').value;
if (fileInput != null || textInput != null) {
var file = null;
if (fileInput.length > 0) {
file = fileInput[0];
}
var form = new FormData();
form.append("Text", textInput);
form.append("File", file);
$.ajax(
{
url: '#Url.Action("AddPost")',
type: "POST",
data: form,
processData: false,
contentType: false
}
);
}
}
EDIT Here is a full demo using the tag helpers asp-action, asp-for and a small JS/jQuery code to intercept the form submission and use Ajax.
1: Controller.
public class FileController : Controller
{
public IActionResult AddPost()
{
return View();
}
[HttpPost]
public void AddPost(AddPostViewModel viewModel)
{
//process the viewModel here
}
}
2: View
#model AddPostViewModel
<form asp-action="AddPost" id="theForm">
<textarea asp-for="Text"></textarea>
<input asp-for="File" size="1" />
<button type="submit">Send</button>
</form>
#section Scripts{
<script>
$("#theForm").submit(function(event) {
event.preventDefault();
$.ajax(
{
url: $(this).prop("action"),
type: "POST",
data: new FormData(this),
processData: false,
contentType: false,
success: function() {
console.log("form sent!");
}
}
);
});
</script>
}
You cant stringify a file data and you cant send file as JSON. You should use FormData to send file with ajax request.
Try to send request as follow
function AddPost() {
var fileInput = document.getElementById('file').files;
var textInput = document.getElementById('addPostText').value;
if (fileInput != null || textInput != null) {
file = null;
if (fileInput.length > 0) {
file = fileInput[length-1];
}
var AddPostViewModel =
{
"Text": textInput,
"File": file
};
var formData = new FormData();
Object.getOwnPropertyNames(AddPostViewModel).forEach(function ( attr, index ) {
var value = AddPostViewModel[attr];
formData.append(attr, value)
});
$.ajax(
{
url: "#Url.Action('AddPost')",
type: "POST",
contentType: false,
processData: false,
data: formData,
}
);
}
}

Passing ViewModel back from controller to Javascript Function MVC

So I have a ViewModel that holds some basic information, and I am taking in an input from the view. Then the input is sent to a .js function that sends it to a controller function that does some work with it. Right now I am just trying to get the Javascript function to connect and display some irrelevant code on the page just to make sure its connected. I make it through everything with no errors, and at the very end I am returned the errorOnAjax Function, inside of the browser tools, that I have written myself. So there is no problem with any of the code that I can see.
My thought is, I am converting the ViewModel to Json wrong in the controller, in turn, it is returning it the wrong way to the Javascript function and giving the error. If anyone has any suggestions, it would be greatly appreciated!
public class MapInfoViewModel
{
public string Place { get; set; }
public string City { get; set; }
public string State { get; set; }
public string URL { get; set; }
}
And I am getting information from the view via an input box
#using (Html.BeginForm())
{
<input type="text" id="name" />
<button id="myButton" onclick="getInfo()">AJAX</button>
}
This is what my Javascript Function looks like. showInfo is just injecting a basic table into the view with just 1 value inside, just to make sure it is connected.
function getInfo(Info) {
var myInfo = document.getElementById('name').value;
$.ajax({
type: "GET",
dataType: "json",
url: "/CreateRoute/DisplayInfo",
data: { 'myInfo': myInfo },
success: showInfo,
error: errorOnAjax
})
}
and my Controller Function
public ActionResult DisplayInfo()
{
string request = Request.QueryString["myInfo"];
MapInfoViewModel info = new MapInfoViewModel()
{
Place = request
};
return new ContentResult
{
Content = JsonConvert.SerializeObject(info),
ContentType = "application/json",
ContentEncoding = System.Text.Encoding.UTF8
};
}
You wrote everything correct code but you just miss the one attribute in view.
you need to mention button type then it will work as per your expectations
<button id="myButton" onclick="getInfo()">AJAX</button>
Now I sharing the complete details of this issue.
Javascript-
function getInfo(Info) {
var myInfo = document.getElementById('name').value;
$.ajax({
type: "GET",
dataType: "json",
url: "/Test/DisplayInfo",
data: { 'myInfo': myInfo },
success: showInfo,
error: errorOnAjax
})
function showInfo(result) {
console.log(result);
}
function errorOnAjax() {
console.log("errorOnAjax");
}
}
View -
#using (#Html.BeginForm())
{
<input type="text" id="name" />
<button type="button" id="myButton" onclick="getInfo()">AJAX</button>
}
Controller-
public ActionResult DisplayInfo()
{
string request = Request.QueryString["myInfo"];
MapInfoViewModel info = new MapInfoViewModel()
{
Place = request
};
return new ContentResult
{
Content = JsonConvert.SerializeObject(info),
ContentType = "application/json",
ContentEncoding = System.Text.Encoding.UTF8
};
}
First return with json in controller.
public ActionResult DisplayInfo(string myInfo)
{
MapInfoViewModel info = new MapInfoViewModel()
{
Place = myInfo
};
return Json(info,JsonRequestBehavior.AllowGet);
}
In Front End use ajax like this.
$( "#myButton" ).click(function() {
let data={myInfo:$('#name').val();};
$.ajax({
type: "GET",
dataType: "json",
url: "/CreateRoute/DisplayInfo",
data: data,
success: function (response){
//do
},
error: function (error){
}
});
});
You need to create JsonResult function, then return Json(info, JsonRequestBehavior.AllowGet) as #sadullah zolfqar answered you.
Please refer to the below link to get the full explanation:
https://www.c-sharpcorner.com/UploadFile/2ed7ae/jsonresult-type-in-mvc/

Passing Javascript variable to Java Controller (Spring-boot)

I'm new to this, so after I have read some solution about this but still not get it.
I have a var id = [] and want to pass it to my controller to delete it from database (SQL server)
My JavaScript
$('#deleteButton').click( function () {
var id = [];
var length = table.rows('.selected').data().length;
for(var i = 0; i < length; i++){
id.push(table.rows('.selected').data()[i][0])
}
$.ajax({
url: "",
//idk to put what into this url
//I think to put an url to show my var but i getting 404 and
//maybe im missing something in controller
//my url to access the project is: localhost:8084
method: 'POST',
data: {
idList: id
},
success: function (data) {
console.log(id);
}
});
console.log(id);
table.rows('.selected').remove().draw( false );
} );
My java controller
#Controller
#ComponentScans(value = { #ComponentScan })
public class CandidateController {
#Autowired
CandidateServiceImp candidateService;
//localhost:8084/manageCandidates is where i show datatable
//and var id = [] is getting from this table
#RequestMapping(value = { "/manageCandidates"})
public String manageCandidatesPage(Model model) {
model.addAttribute("listCandidates",candidateService.getAllCandidates());
return "manageCandidates";
}
}
Please instruct me to get var = id[] in controller
Thanks alot
There are three processes.
Add content-type: application/json in client-side ajax.
And enclose the data in JSON.stringify.
If the server-side Model is properly structured, add #RequestBody before the Model.
Use JSON:
Controller :
#RequestMapping(value = "/manageCandidates", method = RequestMethod.DELETE)
public #ResponseBody String manageCandidatesPage(HttpServletRequest request,#RequestBody String idjson) throws Exception
System.out.println("id"+idjson);
}
Ajax:- data: JSON.stringify(id),
$.ajax({
url: "",
type: "",
async: false,
processData: false,
contentType: "application/json; charset=utf-8",
data: JSON.stringify(id),
success: function(data) {
response = data;
}
});

FormData Values in Razor HTML page, getting in C# Method

I have following input element in razor view page
<input type="file" id="uploadFile" name="FileUpload" multiple="multiple" />
using following script I'm binding data to this ForData
$('#uploadFile').on('change', function()
{
var fd = new FormData();
var files = $('#uploadFile')[0].files;
for (var i = 0; i < files.length; i++)
{
if (files[i].size < 5242880)
{
fd.append("myFiles", files[i])
}
}
});
I'm trying to get these files in C# method like following
[HttpPost]
public ActionResult SomeAction(ModelClass model)
{
var attchaedfiles = System.Web.HttpContext.Current.Request.Files["myFiles"];
for (int i = 0; i < attchaedfiles.Count; i++)
{
if (!string.IsNullOrEmpty(attchaedfiles[i].FileName))
{
....
}
}
}
but here I'm getting folllowing errors
Operator '<' cannot be applied to operands of type 'int' and 'method
group'
Cannot apply indexing with [] to an expression of type
'System.Web.HttpPostedFile'
In your ajax script, make sure you include these:
$.ajax({
url: yourUrl,
type: 'POST',
// Needed for FormData submit
processData: false,
// Needed for FormData submit
contentType: false,
data: fd,
dataType: 'json',
success: function () {
// Success things
},
error: function () {
// Error things
},
complete: function () {
// Complete things
}
});
And that your form code includes enctype = "multipart/form-data":
#using (Html.BeginForm(null, null, FormMethod.Post, new { #action = YourAction, id = "your_id", enctype = "multipart/form-data" }))
Try the following approach that checks possible conditions regarding to file uploads:
Model:
public class ExperimentViewModel
{
public int Id { get; set; }
[DataType(DataType.Upload)]
public IEnumerable<HttpPostedFileBase> FileUpload { get; set; }
//other properties
}
Controller:
if (model.FileUpload != null)
{
if (model.FileUpload.Count() > 0)
{
foreach (var upload in model.FileUpload)
{
if (upload != null && upload.ContentLength > 0)
{
//your stuff
}
}
}
}
You can also look at my answer on How to display images in MVC.

Viewmodel contents null after ajax call?

I am creating an ASP.NET MVC application. I am currently developing a search page where both the search box and the table of results are displayed on the same page. To do this I have used Partial Views and AJAX/JSON calls with a viewmodel. After entering the two search terms in the textbox, both are null in the controller after being passed through ajax.
Here is the code:
ViewModel:
public class ExampleViewModel
{
public string search { get; set; }
public string search2 { get; set; }
}
Controller:
[HttpPost]
public ActionResult Search(ExampleViewModel searchTerm)
{
var searchList = db.UserLists.Where(x => x.LastName.Contains(searchTerm.search));
return PartialView("_SearchResultsPartial", searchList);
}
Body of Index View:
<body>
<div>
#Html.TextBoxFor(model => model.search)
#Html.TextBoxFor(model => model.search2)
<input type="submit" value="Search" onclick="return getSearchResults()"/>
</div>
<div id="search-results">
</div>
<script>
var exViewModel = {
search: $('#search').val(),
search2: $('#search2').val()
}
function getSearchResults() {
$.ajax({
type: "POST",
data: JSON.stringify(exViewModel),
dataType: "json",
contentType: "application/json",
url : "/View/Search/",
success: function (result) {
$("#search-results").html(result);
}
});
}
</script>
Again, after setting a breakpoint on the Search [POST] method, the ExampleViewModel's terms are null.
At first sight, it seems that you have to retrieve the values within the function scope:
function getSearchResults() {
//Read these values on button click
var exViewModel = {
search: $('#search').val(),
search2: $('#search2').val()
}
$.ajax({
type: "POST",
data: JSON.stringify(exViewModel),
dataType: "json",
contentType: "application/json",
url : "/View/Search/",
success: function (result) {
$("#search-results").html(result);
}
});
}
Otherwise, the exViewModel is just determined on page load.

Categories

Resources