Some JSON fields showing up as NULL when hitting MVC Controller method - javascript

After submitting an ajax call, I have confirmed in the request header that all the json fields have a value. What I do not understand is that when I debug on the server side, only the DateEntered field has a value (parsed into a DateTime object). When I put the same information in using Postman, it works just fine on the server (all the fields have a value).
Controller method:
[HttpPost]
public JsonResult SaveJobApplication(ApplicationFormObject jobApplicationObject)
{
return Json(_jobApplicationController.SaveJobApplication(jobApplicationObject), JsonRequestBehavior.AllowGet);
}
Ajax call:
$.ajax({
url: 'http://myurl.com/SaveJobApplication',
data: JSON.stringify(applicationInfo),
contentType: 'application/json',
type: 'POST'
}).done(function(message) {
// do some stuff
});
Here is the context:
The ajax request is coming from a different origin 'http://somedomain.com' than my server origin 'http://myserverdomain.com'. I have implemented CORS in the Web.Config file like so:
...
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
...
This has been tested and it is working fine (My server is able to grant ajax requests from other origins).
The json object that I am submitting is like this:
var applicationInfo = {
FirstObject: {
'NameFirst': 'blah blah',
'NameLast': 'blah blah blah',
'DateEntered': '2012-5-5'
},
SecondObject: {
'LastJob': 'blah blah',
'ReasonQuit': 'blah blah blah'
}
}
The class/objects on the server are like this:
// Object that ajax is utilizing
public class ApplicationFormObject
{
public FirstObject FirstObject { get; set; }
public SecondObject SecondObject { get; set; }
}
public class FirstObject
{
public string NameFirst { get; set; }
public string NameLast { get; set; }
public DateTime? DateEntered{ get; set; }
}
public class SecondObject
{
public string LastJob { get; set; }
public string ReasonQuit { get; set; }
}
Important Information
The json object that I am sending is created dynamically. I actually loop through the form elements via ajax .each. For each element I am adding it to an object like so:
var applicationInfo = {};
$('form input, form select').each(function() {
var that = $(this);
if(isValid(that)) {
applicationInfo["'" + that.attr('id') + "'"] = that.val();
}
});
When I look at the request header, it shows the JSON as being in such format:
{
...
'demoObject': "Value of demo object"
...
}
However, when I test it on Postman, the object is not created dynamically. I explicitly fill in the json object one by one for test data. When I look at the request header for this method, it shows the JSON as being in such format:
{
...
demoObject: "Value of demo object"
...
}
the difference being that the second example does not have single quotes, and the first one does. Hope this information makes sense. Please let me know how I can clarify.

You are passing an invalid Model.
Modify your code as follows :
[HttpPost]
public JsonResult SaveJobApplication(JobApplication jobApplication)
{
return Json(_jobApplicationController.SaveJobApplication(jobApplicationObject), JsonRequestBehavior.AllowGet);
}

Related

How do I access data returned from a controller invoked by an ajax call in an MVC View

I have an MVC 5 view with the following JavaScript which is getting an error after invoking an action method on a controller:
<script type="text/javascript">
$('#ddlvendors').change(function () {
var descHtml = "";
var vendorId = $(this).val();
$.ajax(
{
type: "POST",
data: { vendorId: vendorId },
url: '#Url.Action("PurchaseOrderVendor")',
datatype: "json",
success: function (aVendorObject) {
alert(aVendorObject.Name);
},
error: function (req, status, error) {
alert(error);
}
});
});
</script>
The controller action method is as follows:
[HttpPost]
public ActionResult PurchaseOrderVendor( int vendorId)
{
Vendor aVendor=VendorServices.GetVendor(vendorId);
return Json(aVendor);
}
The vendor object being returned is as follows:
public class VendorViewModel
{
public int VendorId { get; set; }
public string Name { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string Description { get; set; }
public string ContactName { get; set; }
public string Phone { get; set; }
}
Using the Visual Studio 2017 debugger I can see the vendor data is correctly getting filled on the controller side. If I don't try to access any member data the ajax call completes without an error. However, when I try to access any part coming in as aVendorObject such as aVendorObject.Name I get a browser error saying "Internal Server Error". How can I fix my success handler in the ajax call so I can access members of the Vendor object being returned from the controller?
Thanks in advance.
The LazyLoading feature of EntityFramework 6 did not have the Vendor object available when it was needed. I added a line in the VendorServices class to turn off LazyLoading which fixed the problem. Below is the method where I turn off LazyLoading for this particular VendorService method:
static public Vendor GetVendor(int aVendorId)
{
Vendor vendor;
using (RgmSiteDAL RgmSiteDALCtx = new RgmSiteDAL())
{
//** Now setting LazyLoadingEnabled to false.
RgmSiteDALCtx.Configuration.LazyLoadingEnabled = false;
vendor = RgmSiteDALCtx.Vendor
.Where(v => v.VendorId == aVendorId)
.FirstOrDefault<Vendor>();
}
return vendor;
}
I found out that I can also fix the problem if I include any navigation properties defined with the Vendor entity as in the following:
vendor = RgmSiteDALCtx.Vendor
.Where(v => v.VendorId == aVendorId)
.Include(v => v.PurchaseOrder) //because is in Vendor navigation property
.FirstOrDefault<Vendor>();
For my situation I will stick with the first solution which sets LazyLoadingEnabled to false. This is because the option to generate my entities from my existing database setup my PurchaseOrder table as a navigation property for my Vendor which I believe is incorrect. My Vendor object does not need anything from my PurchaseOrder entity when I query for Vendor information. I will look into removing the PurchaseOrder navigation property from my Vendor entity because I believe it was incorrectly setup by the create entities from database tool in Visual Studio.

Posting to ASP.NET WebApi server from AngularJS client

I'm trying to post strings from an AngularJS application (using $http) to a server built on ASP.NET WebApi, but I get 404 as soon as I add a parameter.
The client code is this
$scope.add = function () {
// ...cut...
$http({ method: "POST", url: url, data: { fileString: "test string" }}).then(
function successCallback(response) {
$log.info(response.data);
}
);
}
The server code is
[HttpPost]
public IHttpActionResult UploadExcel(string fileString) {
// cut
}
I get a 404, but if I remove the parameter on server side it works, so i can use a server side code like this
[HttpPost]
public IHttpActionResult UploadExcel() {
// cut
}
What is wrong? Should I pass the data in a different way? I tried different combination but I can't get it work.
What you want to do is send a string, not a JSON object as you are doing right now with { fileString: "test string" }. When I want to send a string, what I normally do is that I send data from Angular like this:
$http.post("/Search/QuickSearch?searchQuery="+ searchString);
And my controller I make ready to receive a string like this:
[HttpPost]
public IHttpActionResult QuickSearch(string searchQuery)
{
// cut
}
If I want to send a JSON object, I tell my controller what it should expect, like this:
[HttpPost]
public IHttpActionResult SaveActivity(ActivityEditForm form);
{
// cut
}
public class ActivityEditForm
{
public int? Id { get; set; }
[Required]
public string Title { get; set; }
public string Description { get; set; }
}
And then send my JSON from Angular like this:
$http.post("/Activity/SaveActivity", { form: activity });
I suggest you should capture the request send by Angular. By default, Angular send parameters in a json string in request body.
I'm not sure wether Asp.net can parse them from json string in body.
So, you can try to add the below codes (also need jQuery)
angular.module('yourApp').config(function ($httpProvider) {
$httpProvider.defaults.transformRequest = function(data){
if (data === undefined) {
return data;
}
return $.param(data);
}
});
The first error is in the controller, [FromBody] should be used with the input parameter.
public IHttpActionResult UploadExcel([FromBody]string fileString)
Then the data variable on the client should be a single string, so
$http({ method: "POST", url: url, data: "test string" }).then(
Anyway I found some issue with this solution later, it seems the simplest but I suggest to avoid it.
Best solution
Thank to #Squazz answer and this SO answer I strongly suggest a change in the webapi controller, client was correct. Just introduce a class to handle a single string and adapt the input parameter
// new class with a single string
public class InputData {
public string fileString { get; set; }
}
// new controller
[HttpPost]
public IHttpActionResult UploadExcel([FromBody] InputData myInput) {
string fileString = myInput.fileString;
// cut
}
This way JSON code from the client is automatically parsed and it's easy to change the data input.
Extra tip
$scope.add angular function was correct as in the question, but here is a more complete example
$scope.testDelete = function () {
var url = "http://localhost/yourAppLink/yourControllerName/UploadExcel";
var data = ({ fileString: "yourStringHere" });
$http({ method: "POST", url: url, data: data }).then(
function successCallback(response) {
console.log("done, here is the answer: ", response.data);
}, function errorCallback(response) {
console.log("an error occurred");
}
);
}

Send JS object to C# Controller using Ajax

I am trying to send multiple objects in js to a controller in C# using an Ajax call.
I have a object in C# called "Person"
which is the next :
public class Person
{
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
and I have the same object In JavaScript.
Then create two persons and I send to the controller.
This is the Ajax call
$.ajax({
url: baseUrl + "/controller/TestPeople",
type: "POST",
data: {
people: people
},
success: function (resp) {
alert("ok");
}
});
This is the post
people[0][Title]:"Mr."
people[0][FirstName]:"fname1"
people[0][LastName]:"Lname1"
people[0][Age]:23
people[1][Title]:"Mr."
people[1][FirstName]:"fname2"
people[1][LastName]:"Lname2"
people[1][Age]:25
but when i receive it in the controller, everything is null
public string TestPeople(Person[] people){
//some code
}
the controller knows that there are 2 people but all the information inside is null.
Any idea why?
To "solve" the problem i change the controller to use FormCollection and it is working, but i would like to know why the other is not working.
Thanks for all.
Try with:
data : JSON.stringify(peopleArray)
In your controller try:
public string Get(Person[] people){
//some code
}

String property not deserialized

I don't understand why only the string property Search.Value is not being deserialized in my ASP.NET MVC5 Controller. Please see this:
The Json-structure sent from the Client:
{
"draw":1,
// ...
"start":0,
"length":50,
"search":{
"value":"This is always null in my controller",
"regex":false
}
}
The model I have server-side:
public class AsyncDataTableRequest
{
public int Draw { get; set; }
public int Start { get; set; }
public int Length { get; set; }
public Search Search { get; set; }
public string Value { get; set; }
}
public class Search
{
public string Value { get; set; }
public bool Regex { get; set; }
}
The controller where I would like to do something with Search.Value:
public JToken AsyncLogFetching(AsyncDataTableRequest req)
{
// req.Search.Value is null here, all other properties seem correct
...
}
Thank you for any help!
Edit:
For a sample search with "NewYork", this the request from the tab "request header" in IE Developer tools:
GET /Log/AsyncLogFetching?draw=3&start=0&length=50&search%5Bvalue%5D=NewYork&search%5Bregex%5D=false&_=1438350434912 HTTP/1.1
The tab "request text" in IE Developer tools says "No data to display".
This is the snippet that does the GET-Request, it's copy & pasted from the jQuery DataTables Pipelining example:
settings.jqXHR = $.ajax({
"type": conf.method, // GET
"url": conf.url,
"data": request,
"dataType": "json",
"contentType": "application/json",
"cache": false,
"success": function (json) {
// ...
}
});
try to use JSON.stringify(yourObject) for send the data from client to controller
please take the reference of following
How to send nested json object to mvc controller using ajax

How to handle parameters on C# server side sent from jQuery POST?

So I'm trying to send the following data from jQuery on the server side like so:
var fd = new FormData();
fd.append('name', 'tyler');
fd.append('hello', 'world');
$.post('/NMISProduct/Index', { submitData: fd}, function(returnedData) {
console.log(returnedData);
}, 'json');
How do I handle this on the server side? Here is what I have, which I'm sure is very wrong:
[HttpPost]
public string Index(string submitData)
{
return submitData;
}
I just want to return what I send to C# back to jQuery so I know it got there. What am I doing wrong?
Your current approach ties you to FormData() and it doesn't take advantage of JSON.Net which is happy and eager to deserialize your object so that you can consume it.
If you truly want to test "full-loop", deserialize to a strongly typed object and return it back to the client as serialized json, building out the matching object on the client instead of using FormData().
$.post('/NMISProduct/Index', { name: 'tyler',hello: 'world' }, function(data) {
console.log(data);
});
[HttpPost]
public ActionResult Index(FormData submitData)
{
return Json(submitData);
}
public class FormData
{
public string Name { get; set; }
public string Hello { get; set; }
}

Categories