mvc server-side validation for jquery ajax post request - javascript

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.

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.

Jquery ajax post sends null when object fields are set with jquery .val() method

I am using Asp.Net Core MVC. I am trying to post an object to action result using jquery http post. When I set my object with static values, i can see all fields are set properly on client side and backend. Posted object is not null.
When I set fields of request with jquery .val() method. Request object is sent as null to backend. Where am I making mistake ?
$("#saveReport").on("click", function () { //SENDS NULL OBJECT
var request = {
BookId: $("#cmbBook").val(),
PageCount: $("#txtPageCount").val(),
Date: $("#dateReport").val(),
Note: $("#txtNotes").val(),
};
//var request = { //SENDS OBJECT PROPERLY
// BookId: 1,
// PageCount: 10,
// Note: "test"
//};
$.ajax({
type: "POST",
url: appUrl + "Report/AddUserReport",
data: JSON.stringify(request),
success: function (data) {
},
error: function (data) {
},
contentType: "application/json; charset=utf-8",
dataType: "json"
});
});
And below is backend
[HttpPost]
public ActionResult<ReadingLogResponse> AddUserReport([FromBody]AddReportModel model)
{
var response = _reportBusiness.AddReport(new AddReadingLogRequest()
{
BookId = model.BookId,
Date = model.Date,
Note = model.Note,
PageCount = model.PageCount
});
return response;
}
jquery .val() method would set the data with string type by default.You need to parse Int.Here is a simple demo like below:
1.Model:
public class AddReportModel
{
public int BookId { get; set; }
public int PageCount { get; set; }
public DateTime Date { get; set; }
public string Note { get; set; }
}
2.View:
<form>
BookID:<input id="cmbBook" type="text" />
PageCount:<input id="txtPageCount" type="text" />
Date:<input id="dateReport" />
Notes:<input id="txtNotes" type="text" />
<input type="button" id="saveReport" value="post" />
</form>
#section Scripts
{
<script>
$("#saveReport").on("click", function () { //SENDS NULL OBJECT
var request = {
BookId: parseInt($("#cmbBook").val()),
PageCount: parseInt($("#txtPageCount").val()),
Date: $("#dateReport").val(),
Note: $("#txtNotes").val(),
};
console.log(request);
console.log(JSON.stringify(request));
$.ajax({
type: "POST",
url: appUrl + "Report/AddUserReport",
data: JSON.stringify(request),
success: function (data) {
},
error: function (data) {
},
contentType: "application/json; charset=utf-8",
dataType: "json"
});
});
</script>
}
3.Controller:
[HttpPost]
public ActionResult<ReadingLogResponse> AddUserReport([FromBody]AddReportModel model)
{
//...
}

How to call Controller method of type HttpPost from Jquery ajax call

I am trying to call a controller function in MVC called UpudateFingerprintStatus from my jquery script. This is a PUT call because i'm updating the status of the desired object. I'm getting a 404 error when i'm trying to call this method.
Here is my JS code:
function updateStatus(statusId, fingerprintId, isDeleted, userId) {
var confirm = window.confirm("Are you sure you wish to change the Fingerprint Status?");
if (confirm) {
$.ajax({
type: "POST",
url: "/Tools/FingerprintTool/UpdateFingerprintStatus",
dataType: "json",
processData: false,
contentType: "application/json; charset=utf-8",
data: JSON.stringify({
userId: userId,
statusId: parseInt(statusId),
fingerprintId: fingerprintId,
isDeleted: isDeleted
}),
sucess: function(resp) {
alert("success");
},
error: function(resp) {
alert("Failure" + resp.description);
}
});
}
}
And here is my Controller method:
[HttpPut]
public JsonResult UpdateFingerprintStatus(int userId, int statusId, int fingerprintId, int isDeleted)
{
var response = _driver.UpdateFingerprintGrantById(userId, fingerprintId, isDeleted, statusId);
return Json(response.Note);
}
Any help would be greatly appreciated!
When we send post , put request it sends complex data type in body so to bind that complex data you need to create class in which all properties should have same name as you sending from front-end.
public class FingerprintStatus{
public string UserId { get; set; }
public int StatusId { get; set; }
public int FingerprintId { get; set; }
public bool IsDeleted { get; set; }
}
[HttpPut]
public JsonResult UpdateFingerprintStatus(FingerprintStatus model)
{
var response = _driver.UpdateFingerprintGrantById(model.UserId, model.FingerprintId, model.IsDeleted, model.StatusId);
return Json(response.Note);
}
This should work:
function updateStatus(statusId, fingerprintId, isDeleted, userId) {
var confirm = window.confirm("Are you sure you wish to change the Fingerprint Status?");
if (confirm) {
var domain = window.location.protocol + "//" + window.location.host;
var url = domain + "/Tools/FingerprintTool/UpdateFingerprintStatus";
var dataContract = {
userId: userId,
statusId: parseInt(statusId),
fingerprintId: fingerprintId,
isDeleted: isDeleted
};
$.ajax({
type: "PUT",
url: url,
dataType: "json",
data: dataContract,
sucess: function(resp) {
alert("success");
},
error: function(resp) {
alert("Failure" + resp.description);
}
});
}
}
[HttpPut]
public JsonResult UpdateFingerprintStatus(int userId, int statusId, int fingerprintId, int isDeleted)
{
var response = _driver.UpdateFingerprintGrantById(userId, fingerprintId, isDeleted, statusId);
return Json(response.Note);
}

Post files and object in the same AJAX request

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));
}

Categories

Resources