jQuery AJAX post to MVC Controller object -- request shows up null - javascript

I know I'm missing something in the details here.
Problem
Despite Googling, trying examples, different formats, etc, the AJAX request that I send always is validated as having all fields empty, but not being null.
I think I'm not sending things in the proper format for the controller to recognize it as an object but I'm not sure what.
Fiddler: What my request looks like
With some dummy data:
Code: Model Class
public class ContactUsMessage
{
public string Email { get; set; }
public string Name { get; set; }
public string PhoneNumber { get; set; }
public string Message { get; set; }
}
Code: WebAPI Controller
[HttpPost]
public HttpResponseMessage NewMessage(ContactUsMessage messageToSend)
{
if (messageToSend == null)
{
var sadResponse = Request.CreateResponse(HttpStatusCode.BadRequest, "Empty Request");
return sadResponse;
}
var messageValidator = new ContactUsMessageValidator();
var results = messageValidator.Validate(messageToSend);
var failures = results.Errors;
var sadString = "";
if (!results.IsValid)
{
foreach (var error in failures)
{
sadString += " Problem: " + error.ErrorMessage;
}
var sadResponse = Request.CreateResponse(HttpStatusCode.NotAcceptable, "Model is invalid." + sadString);
return sadResponse;
}
else
{
SendContactFormEmail(messageToSend.Email, messageToSend.Name, messageToSend.PhoneNumber, messageToSend.Message);
}
Code: JavaScript on Page
function sendSubmissionForm() {
var dataObject = JSON.stringify(
{
messageToSend: {
'Email': $('#inpEmail').val(),
'Name': $('#inpName').val(),
'PhoneNumber': $('#inpPhone').val(),
'Message': $('#inpMessage').val()
}
});
$.ajax({
url: '/api/contactus/newmessage',
type: 'POST',
done: submissionSucceeded,
fail: submissionFailed,
data: dataObject
});
}

When you JSON.stringifyied your data object you converted it to JSON. But you forgot to set the Content-Type request header and the Web API has no way of knowing whether you are sending JSON, XML or something else:
$.ajax({
url: '/api/contactus/newmessage',
type: 'POST',
contentType: 'application/json',
done: submissionSucceeded,
fail: submissionFailed,
data: dataObject
});
Also when building the JSON you don't need to wrap it in an additional property that matches your method argument name. The following should work as well:
var dataObject = JSON.stringify({
'Email': $('#inpEmail').val(),
'Name': $('#inpName').val(),
'PhoneNumber': $('#inpPhone').val(),
'Message': $('#inpMessage').val()
});

Related

json string on POST to MVC action method using AJAX is null

I am getting a hard time to find out why the string sent via AJAX request is null. Console.WriteLine(data) shows empty. Status is 200 OK. If I add some code to parse the string received, I get an error stating that JObject.Parse cannot be null. I don't know what am I missing. The javascript code is ok. The action method also seems ok, but my knowledge on Asp.Net Core and MVC is very scarce, so I am not sure. Can someone please point out what am I missing?
The javascript code:
let obj = {email: email_address.value};
let objStringified = JSON.stringify(obj);
$.ajax({
type: 'POST',
contentType: 'application/json; charset=UTF-8',
data: objStringified,
url: '#Url.Action("ReturnCheckAccountDuplication")',
dataType: 'text',
success: function(data) {
console.log(data);
},
error: function(error) {
console.log("Keep trying", error);
}
});
C# code:
[HttpPost]
public ActionResult ReturnCheckAccountDuplication([FromBody] string data)
{
Console.WriteLine(data);
JObject jObject = JObject.Parse(data);
string email = (string)jObject["email"];
bool emailExists = CheckAccountDuplication.Get(email);
string returnResult = emailExists.ToString();
return Content(returnResult);
}
The solution on the controller side is
public class AccountCheckModel
{
public string Email { get; set; }
}
[HttpPost]
public ActionResult ReturnCheckAccountDuplication([FromBody] AccountCheckModel data)
{
string result = CheckAccountDuplication.Get(data.Email).ToString();
return Content(result);
}
Thanks to all the members who commented on my problem, especially John Glenn who provided a solution. I had been trying for several days but without success. My knowledge of Asp.Net Core is very poor indeed. Thank you very much.
The easiest solution is to create a model representing the JSON data that your controller will receive. For example, create a class like so:
public class AccountCheckModel
{
public string email { get; set }
}
Then, use it as the parameter for your controller method:
public ActionResult ReturnCheckAccountDuplication([FromBody] AccountCheckModel data)
This is the preferred way to access the request body. To get the request body as a string, you have to jump through some serious hoops.
An alternative way to send your data via AJAX to your Controller:
var json = {
email: email_address.value
};
$.ajax({
type: 'POST',
data: {'json': JSON.stringify(json)},
url: '#Url.Action("ReturnCheckAccountDuplication")',
dataType: 'json',
success: function(data) {
console.log(data);
},
error: function(error) {
console.log("Keep trying", error);
}
});
And your Controller:
[HttpPost]
public ActionResult ReturnCheckAccountDuplication(string json)
{
Console.WriteLine(json);
JObject jObject = JObject.Parse(json);
string email = (string)jObject["email"];
bool emailExists = CheckAccountDuplication.Get(email);
string returnResult = emailExists.ToString();
return Content(returnResult);
}

Access form data in C# controller from AJAX post

I am sending form data to a c# controller using AJAX, however I don't know how to access the data inside the controller. I am trying to pass the form data into the controller as a Person object but I am just returning system.Models.Person. I am new to C# so any help would be greatly appreciated, thanks a lot.
Javascript
$('#myForm').submit(function(e){
e.preventDefault();
const formData = new FormData(e.target);
$.ajax({
url: '/Home/GetFormData',
type: 'POST',
data: {formData: formData},
success: function(resultData){
console.log(resultData)
},
error: function(){
//do something else
}
})
}
Model
public class Person
{
public string name { get; set; }
public string age { get; set; }
}
Controller
public string GetFormData(Person formData)
{
string name = formData.name.ToString();
return name;
}
The following post will help you
Post Data Using jQuery in ASP.NET MVC
Your code should be
Model class Person.cs
public class Person
{
public string name { get; set; }
public string age { get; set; }
}
jQuery function to get the form data, I am assuming here you have submit button on your form
$(document).ready(function () {
$("#btnSave").click(function () { //Your Submit button
$.ajax(
{
type: "POST", //HTTP POST Method
url: "Home/GetFormData", // Controller/View
data: { //Passing data
name: $("#txtname").val(), //Reading text box values using Jquery
age: $("#txtage").val(),
}
});
});
});
Your HomeController method
[HttpPost]
public ActionResult GetFormData(Person obj)
{
string name = obj.name;
string age = obj.age;
//Once you have data here then you can pass anywhere i.e. database or some other method
return View();
}
Form values in the controller
Let me know, if any clarification required.
Use serialize if you will send form values:
$form = $(this).serialize();
Use FormData if you be sending a file for upload and alike.
And on your data declaration, set it as is (without declaring it as a literal JS object)
data: $form
The final code would look like this:
$('#myForm').submit(function(e){
e.preventDefault();
$form = $(this).serialize();
$.ajax({
url: '/Home/GetFormData',
type: 'POST',
data: $form,
success: function(resultData){
console.log(resultData)
},
error: function(){
//do something else
}
})

ASP Net Core3.1 AJAX Post Sending NULL to Controller

It has been 3 days am trying to sending the [POST] form data using ajax, Javascript & HTML into MVC controller but getting null.
Please find the controller and ajax code please help me on this also let me know is it possible or not to send the data from ajax to mvc controller?
I am beginner .....thanks in advance.
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> CreateNewBug([FromBody] BugTrackerRequest bugTrackerRequest)
{
// BugTrackerResponse bugTrackerResponse = null;
if (ModelState.IsValid)
{
var Request = await _projectDetails.CreateNewBug(bugTrackerRequest);
if (Request > 0)
{
BugTrackerResponse bugTrackerResponse = new BugTrackerResponse();
bugTrackerResponse.Issuccess = true;
// return Ok(new {Messgage="Data save successfully in the DB"});
return Ok();
}
}
return StatusCode(500, new { Message = "Something went wrong" });
// return bugTrackerResponse;
//return StatusCode();
}
public class BugTrackerRequest:APIResponse
{
public int TicketId { get; set; }
public string ProjectName { get; set; }
public string ProjectDescription { get; set; }
public string Title { get; set; }
public string Status { get; set; }
public string AssignTo { get; set; }
public string AssignFrom { get; set; }
public byte[] Attachment { get; set; }
public string Impact { get; set; }
public string Platform { get; set; }
public string Priority { get; set; }
public string BugType { get; set; }
public DateTime CreatedDate { get; set; }
}
}
function savedetails() {
let saveuidetails = new BugdetailRequestclass();
saveuidetails.ProjectName = $('#projectprojectname').val();
saveuidetails.ProjectDescription = $('#description').val();
saveuidetails.Title = $('#title').val();
saveuidetails.Status = $('#status').val();
saveuidetails.AssignTo = $('#assignto').val();
saveuidetails.AssignFrom = $('#assignfrom').val();
saveuidetails.Attachment = $('#Attfileupload').val;
saveuidetails.Impact = $('#Priority').val();
saveuidetails.Platform = $('#platform').val();
saveuidetails.Priority = $('#Priority').val();
saveuidetails.BugType = $('bugtype').val();
saveuidetails.CreatedDate = $('#currentdate').val();
$.ajax({
type: 'POST',
url: '/TicketController1/CreateNewBugFromBody',
dataType: "json",
contentType: 'application/json',
data: JSON.stringify(saveuidetails),
success: function (data) {
console.log('success', data);
},
error: function () { alert('Exeption:'); }
});
}
Your URL in POST is wrong, please change
/TicketController1/CreateNewBugFromBody
to
/TicketController1/CreateNewBug
Please verify that your controller class is named TicketController1.
To start with, please comment out
saveuidetails.Attachment = $('#Attfileupload').val;
in js and
public DateTime CreatedDate { get; set; }
public byte[] Attachment { get; set; }
When controller method is working, you may look at the Attachment which will be a challenge.
You basically have three choices (https://stackoverflow.com/a/4083908/14072498):
Base64 encode the file, at the expense of increasing the data size by
around 33%, and add processing overhead in both the server and the client
for encoding/decoding.
Send the file first in a multipart/form-data POST, and return an ID to the
client. The client then sends the metadata with the ID, and the server re-
associates the file and the metadata.
Send the metadata first, and return an ID to the client. The
client then sends the file with the ID, and the server re-associates the
file and the metadata.
Else, your code shown here looks OK to me, and there is no problem using a MVC controller for this. If controller contains API methods only, you should extend from ControllerBase instead of Controller, and annotate controller with [ApiController]. The latter invokes model validation automatically.
When implementing new API end-points, always start with something simple and verify with e.g. Postman that you can reach your new end-point.
url: '/TicketController1/CreateNewBugFromBody',
public async Task<IActionResult> CreateNewBug([FromBody] BugTrackerRequest bugTrackerRequest)
First, check your request URL and the action method, it seems that you are submitting the form to the CreateNewBugFromBody method, instead of CreateNewBug action method. So try to change your code as below (I assume your controller name is TicketController1 and you want to submit to the CreateNewBug method):
$.ajax({
type: 'POST',
url: '/TicketController1/CreateNewBug',
dataType: "json",
contentType: 'application/json',
data: JSON.stringify(saveuidetails),
success: function (data) {
console.log('success', data);
},
error: function () { alert('Exeption:'); }
});
Second, please check your JQuery object BugdetailRequestclass, in the action method, it receives a BugTrackerRequest object. So, try to modify your code as below (please change the request url and the jquery selector value to yours):
function savedetails() {
var saveuidetails = {}; //define a object
saveuidetails.ProjectName = $('#ProjectName').val();
saveuidetails.ProjectDescription = $('#Description').val();
saveuidetails.Title = $('#Title').val();
saveuidetails.Status = $('#Status').val();
saveuidetails.AssignTo = $('#AssignTo').val();
saveuidetails.AssignFrom = $('#AssignFrom').val();
saveuidetails.Attachment = $('#Attfileupload').val;
saveuidetails.Impact = $('#Priority').val();
saveuidetails.Platform = $('#Platform').val();
saveuidetails.Priority = $('#Priority').val();
saveuidetails.BugType = $('#BugType').val();
saveuidetails.CreatedDate = $('#CreatedDate').val();
$.ajax({
type: 'POST',
url: '/Home/CreateNewBug',
dataType: "json",
contentType: 'application/json',
data: JSON.stringify(saveuidetails),
success: function (data) {
console.log('success', data);
},
error: function () { alert('Exeption:'); }
});
}
Besides, you could add a breakpoint in the JavaScript resource and CreateNewBug action method, and check whether you could get the correct data before/after send Ajax request.
Screenshot as below:
JavaScript debug screenshot (using F12 developer tools)
Action method debug screenshot:

JSON Object - JavaScript, C#, MVC

I have this for that fills an array, where the cont came from View
function GenerateJSON(cont) {
var songs= [];
for (var i = 0; i <= cont; i++) {
songs[i] = {
id: i,
genre: $(".genre" + i).val(),
song: $(".song" + i).val()
}
}
$.ajax({
url: "Generate",
type: 'POST',
dataType: "json",
data: { songs: JSON.stringify(songs) },
success: function (data) {
}
})
}
On Controller, i got only one block music
example:
songs= [{"id":0,"genre":"","song":"","id":1,"genre":"","song":"","id":2,"genre":"","song":""}]
I want this:
songs=[{"id":0,"genre":"","song":""},{"id":1,"genre":"","song":""},{id":2,"genre":"","song":""}]
Controller
public JsonResult Generate(string[] songs)
{}
Using a string array as the parameter does not make sense to me. Now you have to make client side code to build some sophisticated string and in server side you have to parse it to get each item's property values.
IMHO, The clean approach is to use a view model and take advantage of MVC model binding. Start by creating a view model to represent your data.
public class SongVm
{
public int Id { set; get; }
public string Genre { set; get; }
public string Song { set; get; }
}
Now use this as the parameter of your action method. Since you want to send a collection of your objects, use List<SongVm> as your parameter.
[HttpPost]
public ActionResult Gerar(List<SongVm> songs)
{
// Simply returning the data with a message property as well
return Json(new { messge ="success", data = songs });
}
Now from the client side code, send the JSON string version of your array, while specifying application/json as the value of contentType property of the option we are passing to the $.ajax method.
var songs = [];
for (var i = 0; i <= cont; i++) {
songs[i] = {
id: i,
genre : "test genre" + i,
song : "test song" + i
};
}
$.ajax({
url: "/Home/Gerar",
type: 'POST',
contentType: "application/json",
data: JSON.stringify(songs),
success: function (data) {
console.log(data);
},
error: function (a, b, c) {
console.log(c);
}
})
Now $.ajax will add the request header Content-Type to the call with the value application/json. As part of model binding, the default model binder will read this request header value and then decide to read the data from the request body(Request payload)
I would also recommend leveraging the Url helper methods like Url.Action to generate the correct relative path to the action method.

Ajax POST and Stringify Confusion

I am learning about POST with Ajax and I've noticed a lot of examples using stringify on static arrays.
In my example I am building array via jQuery objects extracted from <input> values.
Jquery
function PostEdit(vData){
var content = JSON.stringify(vData); //content = "[{"Id":"1","Date":"7/12/2017 12:00:00 AM"}]"
$.ajax({
url: '#Url.Action("Index", "PostViewData")',
type: "POST",
data: JSON.stringify({ ViewData : vData }),
contentType: "application/json",
success: function (result) {
alert("success" + result);
},
error: function (result) {
alert("failure" + result);
}
});
return;
}
Controller
[HttpPost]
public ActionResult Index(List<DataViewModel> ViewData )
{
if(ViewData != null)
{
var json = new { success = true };
return Json(json);
}
return Json(false);
}
ViewModel
public class DataViewModel
{
public DataViewModel(string id, string date)
{
Id = id;
Date = date;
}
public string Id { get; set; }
public string Date { get; set; }
}
Where DataViewModel is a class that consists of two values, Id, and Date which correspond to my JS object.
Since vData enters the function as value vData = [Object], When I call .stringify(vData) it returns content = "[{"Id":"1","Date":"7/12/2017 12:00:00 AM"}]"
The value of content above is how I see most examples structured before stringify such as the example here.
Once in this format, this is when most responses, examples call stringify anyway.
Now when I call .stringify(ViewData : vData) I dont even make it to the controller. Ajax fails to post. On the contrary when I call .stringify(ViewData : content), I make it to the controller, but with a null value. What am I missing / misunderstanding?
I'm looking for a better explanation of Ajax Post and Stringify, and how it interacts with the controller parameter.
Just add parameterless constructor to your model. With that change, your code will work as it is. ASP is unable to parse your json as DataViewModel since it's trying to call default constructor that doesn't exists.
public class DataViewModel
{
public DataViewModel()
{
}
//...other methods and members here
}
Please try the solution below.
There's another way of doing this
function PostEdit(vId, vDate){
$.ajax({
url: '/PostViewData/Index' // it should be '/controller/method'
type: "POST",
data: JSON.stringify({ Id: vId, Date: vDate}),
contentType: "application/json",
success: function (result) {
alert("success" + result);
},
error: function (result) {
alert("failure" + result);
}
});
return;
}
[HttpPost]
public ActionResult Index(string Id, string Date )
{
if(Id != null)
{
var json = new { success = true };
return Json(json);
}
return Json(false);
}
Update: In the controller method, it should be string id, string date
Update: The constructor should be parameterless. From the answer mentioned below
public DataViewModel()
{
}

Categories

Resources