Post files and object in the same AJAX request - javascript

I have some data and files that should be posted in one same AJAX request. Tried some solutions but I always get null in the controller (files are sent fine and when I change Tester class to simple string it also works).
My JS:
function sendAjaxWithFile (formData, successCallback, errorCallback) {
successCallback = successCallback || function () { };
errorCallback = errorCallback || function () { };
$.ajax({
url: "/Test/Save",
type: "POST",
data: formData,
cache: false,
processData: false,
contentType: false,
success: successCallback,
error: errorCallback
});
}
var data = new FormData();
data.append("tester", { Name: "QWERTY" });
data.append("someFile", file);
$scope.sendAjaxWithFile(data, function (response, textStatus, jqXHR) {
}, function (jqXHR, textStatus, errorThrown) {
});
And the server side code:
[AjaxOnly]
[HttpPost]
[Route("Save")]
public async Task<JsonResult> Save(Tester tester, HttpPostedFileBase someFile)
{
return await Task.FromResult(Json(0));
}
Tester class:
public class Tester
{
public string Name { get; set; }
public DateTime Date { get; set; }
}

I did a workaround, because I don't think it can be resolved in a normal way...
My solution is to send string data which is serialized from my JS object.
data.append("serializedJsonString", JSON.stringify({ Name: "QWERTY" })); // I can serialize what I want to
I needed to change the parameter of my Save method to get JSON string data and convert it into Tester class manually:
[AjaxOnly]
[HttpPost]
[Route("Save")]
public async Task<JsonResult> Save(string serializedJsonString, HttpPostedFileBase someFile)
{
var decodedJson = HttpUtility.UrlDecode(serializedJsonString);
var jTester = JObject.Parse(decodedJson);
var tester = new Tester { Name = jTester["Name"].ToString() };
return await Task.FromResult(Json(0));
}

Related

Return parameter null in controller from ajax

I don't know what happened the value sent to the controller is always null, even though in the console.log the value is there, please I need help
this is my ajax:
$('#ddlItemName').change(function () {
var ItemCode = $('#ddlItemName').text();
if (ItemCode != '') {
var RequestParam = {
search: ItemCode
}
console.log(RequestParam);
$.ajax({
url: '/Order/CustomerItemOrders',
type: 'POST',
data: JSON.stringify(RequestParam),
contentType: 'application/json; charset=utf-8',
success: function (data) {
alert(data[0].Name);
},
error: function (data) {
toastr.error(data);
}
});
}
$('#ddlItemName').text('');
});
This is my controller :
[HttpPost]
public JsonResult CustomerItemOrders([FromBody] string search)
{
var result = _order.BindCustomerOrders(search);
return Json(result.data);
}
This is my error :
enter image description here
I've tried adding '[FromBody]' but the value parameter still doesn't get sent
I recomend you add the parameter to query
If you insist on pass the value with request body
Try creat a model:
public class SomeModel
{
public string search{get;set;}
}
in your controller:
public JsonResult CustomerItemOrders([FromBody] SomeModel somemodel)
{
.......
}

Ajax POST an object with javascript, but the value in backend is null, why?

So on button click there is a function sendEmail(). Alert is working fine, I can see my datas there. But on backend I can't see anything, just everything is null.
function sendEmail() {
var datas = new Object();
datas.mail = $('#contactDropdownList').val();
datas.mailobject = $('#emailObject').val();
datas.text = $('#emailText').val();enter code here
alert(datas.mail + datas.mailobject + datas.text);
$.ajax({
type: "POST",
dataType: "json",
url: "/Email/sendEmail",
contentType: 'application/json; charset=UTF-8',
data: JSON.stringify({ items: datas }),
success: function (data) {
console.log(data);
//do something with data
},
error: function (jqXHR, textStatus, error) {
//log or alert the error
console.log(error);
}
});
}
C# code:
public class MyClass
{
public string Email { get; set; }
public string Object { get; set; }
public string Text { get; set; }
}
[HttpPost]
public IActionResult sendEmail(MyClass items)
{
return Json(new { data="Ok" });
}
items.Email, items.Object and items.Text are null.
And the return valu is null as well, because in javascript success: function (data) { console.log(data);
is empty string.
What can be the problem? Thank you!
Model binder expects json content to match C# class. Your datas object should look like that
var datas = {
email: $('#contactDropdownList').val(),
object: $('#emailObject').val(),
text: $('#emailText').val()
}
Since you wrapped your object ({ items: datas }), you may think it will be mapped to sendEmail(MyClass items), but in reality items name does not matter, you can change variable name to any other name you like
Make sure you apply [FromBody] attribute to your parameter like that
[HttpPost]
public IActionResult sendEmail([FromBody]MyClass items)
Complete demo:
<script>
function sendSmth() {
var data = {
Email: 'email',
Object: 'object',
Text: 'text'
};
$.ajax({
type: "POST",
dataType: "json",
url: "/home/index",
contentType: "application/json",
data: JSON.stringify(data),
success: function (datas) {
console.log(datas)
}
})
}
</script>
And controller
[HttpPost]
public IActionResult Index([FromBody]MyClass obj)
{
return View();
}
As someone has noted, you have a mismatch between what you're sending to the controller and what the model the modelbinder is expecting. You can also vastly simply your AJAX code:
function sendEmail() {
var data = {
Email: $('#contactDropdownList').val(),
Object: $('#emailObject').val(),
Text: $('#emailText').val()
};
$.post("/Email/sendEmail", data)
.done(function (response) {
console.log(response);
//do something with response
})
.fail(function (jqXHR, textStatus, error) {
//log or alert the error
console.log(error);
});
}
You don't really need to specify the content type or data type - the $.post helper's defaults work just fine for what you've shown.

RequestBody is null in controller

I'm trying to send JSON object from frontend to backend via jQuery AJAX.
The ajax call is performed successfully on the requested path "/survey" with a POST method.
Problem is, my #RequestBody final HmmSurveyForm hmmSurveyForm has null values for my fields "answer1" and "heading".
When I checked request in google chrome developer request is sent:
But the response is null for populated fields from frontend:
I have following code in frontend:
postSurvey: function() {
$.ajax({
url: this.encodedContextPath + "/survey",
type: 'POST',
dataType: 'json',
contentType: 'application/json',
data: ACC.hmmSurvey.getJSONDataForSurvey(),
async: true,
success: function (response) {
console.log(response);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log("The following error occurred: " + textStatus, errorThrown);
}
});
}
getJSONDataForSurvey: function () {
var json = [];
json.push({"answer1": "1"});
json.push({"heading": "Test"});
return JSON.stringify({"hmmSurveyForm": json});
}
and in backend:
#RequestMapping(value = "/survey", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody HmmSurveyForm postSurvey(#RequestBody final HmmSurveyForm hmmSurveyForm, final Model model) {
System.out.println(hmmSurveyForm);
return hmmSurveyForm;
}
public class HmmSurveyForm {
private String heading;
private String answer1;
// getter, setters
}
You are declaring your RQ body incorrectly in JS
var json = [];
json.push({"answer1": "1"});
json.push({"heading": "Test"});
console.log({"hmmSurveyForm": json});
which has the root hmmSurveyForm as an array of distinct objects, which has no relation to what your backend expects.
You should be using the code below;
var json = {};
json["answer1"] = "1";
json["heading"] = "Test";
console.log({"hmmSurveyForm": json});
Check more on JSON Object in JS here

AJAX call: Invalid web service call, missing value for parameter

My ajax call fails with the message in question.
[WebMethod(EnableSession = true)]
public static string UpdateTotalPrice(List<TicketPriceAjax> jsonTickets)
{
// some server-side processing
return "a string value";
}
The object Iʻm trying to pass
public class TicketPriceAjax
{
public string Fullname { get; set; }
public string Price { get; set; }
public string TicketDescription { get; set; }
}
My javascript which gets invoked on a change event
$("select.combobox").change(function(e) {
var ticketsArray = GetTicketsArray();
postTotalPrice(ticketsArray);
});
function GetTicketsArray() {
var tickets = {};
var prices = [];
tickets.prices = prices;
$("#divFullNames div.row").each(function () {
var price = {
"Fullname": $(this).find("input").val(),
"Price": $(this).find("select").val(),
"TicketDescription": $(this).find(":selected").text()
};
tickets.prices.push(price);
});
return tickets;
};
function postTotalPrice(prices) {
$.ajax({
type: "POST",
url: "Details.aspx/UpdateTotalPrice",
data: JSON.stringify(prices),
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
success: function (data) {
UpdateTotalPrice(data);
},
error: function(data, textStatus, jqXHR) {
console.log('error!', data, textStatus, jqXHR);
}
});
};
What am I doing wrong?
Change data part to this
data: JSON.stringify({jsonTickets:prices})
Your webmethod expects a parameter with name jsonTickets so you need to specify parameter name in data part.
Also you do not need to assign tickets.prices simply create an array and push objects in it and pass it to webmethod.This way you are creating a list and than assigning list to its property prices and in webmethod you are expecting a list.
var tickets = [];
$("#divFullNames div.row").each(function () {
var price = {
"Fullname": $(this).find("input").val(),
"Price": $(this).find("select").val(),
"TicketDescription": $(this).find(":selected").text()
};
tickets.push(price);
This will pass list to webmethods.

mvc server-side validation for jquery ajax post request

How this can be done ?
For example in my model i have
[Required]
[DataType(DataType.EmailAddress)]
[RegularExpression(#"[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}", ErrorMessage = "Incorrect email")]
public string EmailTo { get; set; }
My current test new controller is
[HttpPost]
public EmptyResult SendAgreementEmail(AgreementReportModel model)
{
bool t = ModelState.IsValid;
return new EmptyResult();
}
ModelState.IsValid is valid even if emailto is null.
And js function
function SendEmailWithJquery(offerID, agreementOfferID, customerID) {
var emailTo = document.getElementById('txtEmailTo').value;
var emailSubject = document.getElementById('txtEmailSubject').value;
var emailBody = document.getElementById('txtEmailBody').value;
var sendData = {
OfferID: offerID,
AgreementOfferID: agreementOfferID,
CustomerID: customerID,
EmailTo: emailTo,
EmailSubject: emailSubject,
EmailBody: emailBody
};
$.ajax({
url: "/Agreement/SendAgreementEmail",
type: "POST",
data: JSON.stringify(sendData),
dataType: 'json',
contentType: 'application/json',
success: function (data, textStatus, jqXHR) {
},
error: function (jqXHR, textStatus, errorThrown) {
}
});
};
Is it possible at all to validate server-side for controller with json object and strong-typed view ?
I have used the same code as of yours, and server side validation is working absolutely fine for me. For simplicity sake I removed all properties, except the email property (as it is causing the main problem).
Model -
public class AgreementReportModel
{
[Required]
[DataType(DataType.EmailAddress)]
[RegularExpression(#"[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}", ErrorMessage = "Incorrect email")]
public string EmailTo { get; set; }
}
Controller Action -
public class AgreementController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public EmptyResult SendAgreementEmail(AgreementReportModel model)
{
bool t = ModelState.IsValid;
return new EmptyResult();
}
}
Index View -
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script>
function SendEmailWithJquery() {
var sendData = {
EmailTo: ''
};
$.ajax({
url: "/Agreement/SendAgreementEmail",
type: "POST",
data: JSON.stringify(sendData),
dataType: 'json',
contentType: 'application/json',
success: function (data, textStatus, jqXHR) {
},
error: function (jqXHR, textStatus, errorThrown) {
}
});
};
</script>
<input type="button" value="Click" onclick="SendEmailWithJquery()" />
When I initiated EmailTo : 'rami#gmail.com, I get ModelState.IsValid to true.
When I initiated EmailTo : null or EmailTo : '', I get ModelState.IsValid to false.
What to do next:
Check your other data types, they might be culprits.
Check you JavaScript input retrieval, document.getElementById, that can be giving your nulls.
Check other parts of code, which can cause the problem, probably code like action filters etc.

Categories

Resources