MVC 4 Ajax Asynchronous File Upload Always Passing Null Value To Controller - javascript

I'm having a problem when trying to upload file asynchronously from ajax to my controller. I have 3 variables to pass (PictureId, PictureName, and PictureFile). The problem lies on my "PictureFile" variable which should be holding the uploaded file itself but instead it always pass null value to the controller.
Here is my view model
public class PictureUpload
{
public int PictureId { get; set; }
public string PictureName { get; set; }
public HttpPostedFileBase PictureFile { get; set; }
}
Here is my controller
public JsonResult EditPicture(PictureUpload picture)
{
//do something here
}
Here is my form
<div class="thumbnail" id="uploadForm">
<form name="uploadForm" enctype="multipart/form-data">
<input type="text" name="fileId" hidden="hidden" />
<input type="file" name="file" style="max-width: 100%" />
<input type="button" name="cancel" value="cancel" />
<span>
<input type="button" name="upload" value="upload" />
</span>
</form>
</div>
Here is my script
$("input[name=upload]").click(function () {
var $pictureId = $("input[name=fileId]").val();
var $pictureFile = $("input[name=file]").get(0).files[0];
$.ajax({
type: 'POST',
url: '#Url.Action("EditPicture", "Restaurant")',
contentType: "application/json",
dataType: 'json',
data: JSON.stringify({ PictureId: $pictureId, PictureName: $pictureFile.name, PictureFile: $pictureFile }),
});
In my controller parameter. "PictureId" and "PictureName" holds the correct value, but "PictureFile" is always null. So it means something is going just not right when the system passes the parameter from ajax to controller. Somehow the system treats "file" type differently from others. Could you help me so the file get passed successfully to the controller and tell me what is wrong with this approach?

As mentioned rightly in the comments use FormData. Below is a code snippet :
var fd = new FormData();
fd.append('file', fileObject);
fd.append('PictureId', pictureId);
fd.append('PictureName', pictureName);
$.ajax({
url: '/Restaurant/EditPicture',
async: true,
type: 'POST',
data: fd,
processData: false,
contentType: false,
success: function (response) {
}
});

You cannot upload files with AJAX. One way to achieve this is to use a hidden iframe which will simulate an AJAX call and perform the actual file upload or use Flash.

Related

Null value when posting data from a html form to a c# controller method using a JavaScript function

I am teaching myself how to program and I am having a hard time identifying an issue with my most recent experiment. The following is within the context of an 'ASP.NET Web Application (.NetFramework) C#' and MVC architecture.
I am attempting to post data from a html form to a c# controller method using a JavaScript function.
The JavaScript function invokes the controller method; however, the string passed to the method always has a null value. (I know that the new 'Organisation' instance is successfully created, as new instances appear with an ID in my database yet with a null name - as per my model).
I have searched similar questions and tested contentType: application/json; charset=utf-8 also; however, my issue persists.
The error reads: System.ArgumentNullException: 'Value cannot be null. Parameter name: s' and occurs at var jsonDataParsed = JObject.Parse(jsonData); in my c# controller method.
I was hoping someone may be kind enough to help me :)
The form:
<form id="createOrganisationForm">
<label for="organisationName">Organisation name</label>
<input type="text" id="organisationName" />
<input type="submit" onclick="createOrganisation()" value="submit" />
</form>
The Javascript function:
function createOrganisation() {
var formData = {
"OrganisationName": $("#organisationName").val()
}
$.ajax({
url: '#Url.Action("CreateOrganisation", "Organisations")',
type: "POST",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
data: JSON.stringify(formData)
})
}
The c# method in a controller:
[HttpPost]
public void CreateOrganisation(string jsonData)
{
var jsonDataParsed = JObject.Parse(jsonData);
var organisationName = jsonDataParsed["OrganisationName"].ToString();
var organisation = new Organisation();
organisation.Name = organisationName;
db.Organisations.Add(organisation);
db.SaveChanges();
}
The model:
public class Organisation
{
public int OrganisationID { get; set; }
public string Name { get; set; }
}
Try this:
function createOrganisation() {
var formData = {
"OrganisationName": $("#organisationName").val()
}
$.ajax({
url: '#Url.Action("CreateOrganisation", "Organisations")',
type: "POST",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
dataType: 'json',
data: {'formData': formData }
})
}
Thank you everyone for your help. Special thanks go to #Teemu for pointing me towards the final solution.
Below is a working solution; I hope this may help others with future issues.
Key changes:
name="organisationName" atrribute added to input
<input type="submit" edited to <button type="button"
"parameter=" added to data: in ajax request
["OrganisationName"] edited to ["organisationName"] in C# method
Please refer to #Teemu advice in the question's comment section for the rationale behind these changes.
The HTML form:
<form id="createOrganisationForm">
<label for="organisationName">Organisation name</label>
<input type="text" id="organisationName" name="organisationName" />
<button type="button" onclick="createOrganisation()">Submit</button>
</form>
The JavaScript function:
function createOrganisation() {
var formData = JSON.stringify({ organisationName: $("#organisationName").val()})
$.ajax({
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
data: "jsonData=" + formData,
url: '#Url.Action("CreateOrganisation", "Organisations")',
type: "POST"
})
}
Helpful note: the above script should be in the view file (not an external file) if you are using a razor #URL.Action
The c# controller method:
[HttpPost]
public void CreateOrganisation(string jsonData)
{
var jsonDataParsed = JObject.Parse(jsonData);
var organisationName = jsonDataParsed["organisationName"].ToString();
var organisation = new Organisation();
organisation.Name = organisationName;
db.Organisations.Add(organisation);
db.SaveChanges();
}

How to receive data included file in asp.net core?

Which model should I use to receive a js data, included a File object and a string, from client? Or which data type should I use for File object in asp.net Core server?
Use ViewModel to receive the file and string , and submit form directly to post these data . Note : add enctype="multipart/form-data" in Form when you want to send files
public class TestViewModel
{
public string Name { get; set; }
public IFormFile file { get; set; }
}
<div class="row">
<div class="col-md-4">
<form asp-action="UploadFile" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<input asp-for="file" class="form-control" />
</div>
<div class="form-group">
<input type="submit" id="btnSubmit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
<span id="result"></span>
</div>
If you want to send form data by js , you could add id="fileUploadForm" and try the javascript like below
#section Scripts
{
<script type="text/javascript">
$(document).ready(function () {
$("#btnSubmit").click(function (event) {
//stop submit the form, we will post it manually.
event.preventDefault();
// Get form
var form = $('#fileUploadForm')[0];
// Create an FormData object
var data = new FormData(form);
// If you want to add an extra field for the FormData
data.append("CustomField", "This is some extra data, testing");
// disabled the submit button
$("#btnSubmit").prop("disabled", true);
$.ajax({
type: "POST",
//enctype: 'multipart/form-data',
url: "/Home/UploadFile",
data: data,
processData: false,
contentType: false,
cache: false,
timeout: 600000,
success: function (data) {
$("#result").text(data);
console.log("SUCCESS : ", data);
$("#btnSubmit").prop("disabled", false);
},
error: function (e) {
$("#result").text(e.responseText);
console.log("ERROR : ", e);
$("#btnSubmit").prop("disabled", false);
}
});
});
});
</script>
}
Controller
[HttpPost]
public async Task<ActionResult> UploadFile(TestViewModel data)
{ }
Which model should I use to receive js data, including a File object and a string
ASP Net Core has the IFormFile container for this purpose. The data is held internally as a stream.
Your action signature for a string and a file would look like,
public IActionResult Action(IFormFile file, string name) { }
Note, the parameter names must match the form data names you use in javascript. I.e,
const fd = new FormData()
fd.append('file' , file)
fd.append('name', 'some string')
This documentation provides full usage examples.

Javascript post String with ajax to backend(java)

I'm programming a commentary box for a Web Client.
I have two tables, one for the Comments and one for the Users. I want to send Input Data from my <input> tags in HTML form to my Java Service. In this Service, I handle the received data. My Problem now is, that I get an HTTP-415 error and I don't know what to do Right now.
I am using AJAX in JavaScript to post the Data.
HTML
ID: <input type="text" name="id" value="1" readonly/> <br/>
Author: <input type="text" name="author"/> <br/>
comment: <input type="text" name="comment"/> <br/>
<button id="submit" type="Button" >Submit</button>
Javascript
function addPost(givenID){
var $author = $("#author");
var $comment= $("#comment");
var $id = $("#id")
$("#submit").on("click", function(){
var post = $author.val()+"*"+ $id.val()+"*"+ $comment.val();
$.ajax({
type: "POST",
url: "api/kommentar",
data: post,
success: function(){
console.log("SUCCESS");
},
error: function(){
console.log("FAILIURE");
}
});
});}
Java
#Path("/kommentar")
public class KommentarService {
#EJB
private KommentarManagement postMgmt;
public KommentarService() { }
#POST
#Consumes("text/plain")
public void addPostsAsJson(String income) {
System.out.println(income);
//CODE TO HANDLE...
}
jQuery's default content type for the Ajax function is 'application/x-www-form-urlencoded; charset=UTF-8'.
Because the service is expecting 'text/plain' the content type needs changed.
Add a content type:
data: post,
contentType: 'text/plain', //<--- insert
success: function(){

Uploading a simple form to Java Spring

I'm simply trying to pass a text input and a file to Java but without success.
The formData seems to be working because I read the formData elements and all seems to be there. I just can't pass it to Java.
HTTP Status 500 - Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Current request is not a multipart request
HTML
<form id="creationForm" method="get" enctype="multipart/form-data">
<input id="testName" class="form-control" name="testName">
<input type="file" name="fileUpload" id="fileUpload"/>
</form>
JavaScript
$(document).ready(function () {
var files = [];
$('#fileUpload').change(function (event) {
files = event.target.files;
});
$('#btnSubmit').click(function (e) {
e.preventDefault();
var formData = new FormData(document.getElementById('creationForm'));
console.log(files[0]);
$.ajax({
type: 'get',
url: '/upload/testCase',
data: formData,
enctype: 'multipart/form-data',
processData: false,
contentType: false,
success: function (result) {
},
error: function () {
}
});
});
});
Java
#RequestMapping(value = "/upload/testCase", method = RequestMethod.GET)
public #ResponseBody void uploadTestCase(#RequestParam("fileUpload") MultipartFile file ) {
//TestCases.upload(file);
System.out.println(file);
}
Spring XML included bean
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
I guess you're using the wrong http-method. Try to use post instead of get? That might solve it.
Spring:
#RequestMapping(value = "/upload/testCase" , method = RequestMethod.POST)
JQuery:
$.ajax({
type: 'post',
...
...
)};
According to https://spring.io/guides/gs/uploading-files/, this is the way your form should be defined to upload a file:
HTML
<form id="creationForm" method="POST" enctype="multipart/form-data" action="/upload/testCase">
<input id="fileName" class="form-control" name="name">
<input id="fileUpload" type="file" name="fileUpload"/>
<button class="form-control">Submit</button>
</form>
Java
#PostMapping("/upload/testCase")
public void uploadTestCase(#RequestParam("fileUpload") MultipartFile file) {
System.out.println(file);
}
In theory, you shouldn't need Javascript code for that.
But maybe you don't want the form to directly post your data, do you?

How to send values and image form javascript to controller in spring MVC

This is the jsp code,
Username: <input type="text" name="user_name"/>
File: <input type="file" name="profile_img" />
<input type="submit" value="Save" onclick="saveProfileData()"/>
And this is the javscript code,
function saveProfileData() {
var user_name = document.getElementById("user_name").value;
var profile_img = document.getElementById("profile_img").value;
$.ajax({
type: "POST",
url: /login/saveProfileData,
data:{
"user_name": user_name,
"profile_img":profile_img
},
success: function(response){
//other code
},
error: function(e){
//alert('Error: ' + e);
}
});
}
#ResponseBody
#RequestMapping(value="/saveProfileData", method=RequestMethod.POST)
public int saveProfileData(#RequestParam(required=false) String user_name, MultipartFile profile_img) {
System.out.println(user_name);
//int i = code for save profile data.
return i;
}
When I click on save button, It gives this error The current request is not a multipart request.
Why this is happening and how to fix this? How can I send the values with image?
Please anyone help me.?
Have you tried adding the encodingtype of the input field for the file, like such:
File: <input type="file" name="profile_img" enctype = "multipart/form-data"/>

Categories