How to send nested json object to mvc controller using ajax - c#

I am working on an ASP.NET MVC application. I have the following view model in c#:
public class ContactModel
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
}
public class PersonModel
{
public ContactModel Contact;
public PersonModel()
{
Contact = new ContactModel();
}
public string FirstName { get; set; }
public string LastName { get; set; }
public string Profession { get; set; }
}
Now i have the same json model at client side which i want to post to server. I am using following jquery ajax:
$.ajax({
url: "address to controller",
type: "post",
data: JSON.stringify(data),
contentType: "application/json",
success: function () {
alert("data saved successfully");
}
});
But only PersonModel properties are get mapped but Contact properties are null. Can anybody please tell me what i am missing??

You need for format your string to proper json -
Say if you model is -
public class ContactModel
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
}
public class PersonModel
{
public ContactModel Contact { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Profession { get; set; }
}
Then you AJAX Post should be like this -
<script>
$(function () {
$('#click1').click(function (e) {
var studentData = {
"FirstName": "Rami",
"LastName": "Vemula" ,
"Contact": { "City": "Hyd"}
};
$.ajax({
url: "#Url.Action("Submit")",
type: "POST",
data: JSON.stringify(studentData),
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function (response) {
alert(response.responseText);
},
success: function (response) {
alert(response);
}
});
});
});
</script>
Then output is going to be -

Create a instance of ContactModel and assign it to contact under PersonModel after creating instance of PersonModel.
Please let me know in case of any clarification needed

If you are using #html helper for properties then form.serialize() method will bind all the properties otherwise if you are using html elements like <input> the assign their name property same as model property.
<input type="text" name="Contact.FirstName" value="#Model.Contact.FirstName"/>

Related

Ajax form post not binding to object in ASP.net core 6 MVC

I cannot figure this out. I have similar code in other areas of my project that works fine. What am I missing?
Why is studentDTO object null?
The Controller Action
[HttpPost("SaveStudent")]
public async Task<IActionResult> SaveStudent(
[Bind(Prefix = "Student")][FromForm] StudentDTO studentDTO
)
{
// blah blah
}
The Class
public class StudentDTO
{
public Guid StudentID { get; set; }
public Guid AccountID { get; set; }
public int TuitionID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public decimal AnnualTuitionCost { get; set; }
public int TuitionMonths { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
}
The AJAX call
var formData = $("#addEditStudentFrm").serialize();
console.log(formData);
$.ajax({
url : '/api/blah/SaveStudent/',
dataType: 'json',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: formData,
type: 'POST',
success: function (result) {
// blah blah
},
error: function (result) {
// blah blah
}
});
The Request
I am hitting the controller action, but I'm not getting the form data. Suggestions?
If I remove [FromForm] I get a response of "415 Unsupported Media Type"
I have been using the information provided here to no avail:
https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-6.0
Figured it out. Prefix needed to be Student. and not Student_ in the name attribute of the form elements:

Pass custom model *with List<CustClass>* through ajax call

I am having a bit of trouble passing my json string to the jsonResult within my controller. All the first-level variables come in fine except for the List<CustClass> which always returns a default empty list when it should be filled with the list of objects (List<>) I passed in.
The ajax call that looks along the lines of:
var model = {
Id: id,
Name: name,
Items: [{
Name: itemName[0],
Color: itemColor[0]
},{
Name: itemName[1],
Color: itemColor[2]
}]
};
$.ajax({
url: "/#path",
type: "POST",
data: JSON.stringify(model),
dataType: "json",
contentType: "application/json; charset=utf-8",
cache: false,
traditional: true
});
With my C# model looking along the lines of
public class MyModel
{
public int Id { get; set; }
public string Name { get; set; }
public class Item {
public string Name { get; set; }
public string Color { get; set; }
}
public List<Item> Items = new List<Item>();
}
And the result:
[HttpPost]
public JsonResult MyResult(MyModel model)
{
// Do Stuff
}
What am I doing wrong here? Is this even possible to do?
Dont instantiate your list to map it properly. Since binding of model takes place after instantiation of the class.
public class MyModel
{
public int Id { get; set; }
public string Name { get; set; }
public class Item {
public string Name { get; set; }
public string Color { get; set; }
}
public List<Item> Items {get; set;}
}

Server not receiving JSON

I have the following viewModel:
public class ProfileLocalizationViewModel
{
public ProfileViewModel Profile { get; set; }
public virtual string LanguageCode { get; set; }
public string Description { get; set; }
}
with the Profile object looking like:
public class ProfileViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsOutlet { get; set; }
public bool IsWholesaler { get; set; }
public bool IsProducer { get; set; }
public List<ProfileLocalizationViewModel> Localizations { get; set; }
}
From the client, I'm sending the following JSON:
{"Profile":{"Id":-1,"Name":"New Profiledsa","IsOutlet":false,"IsWholesaler":false,"IsProducer":false,"Localizations":null},"LanguageCode":"en","Description":"Description for selected language","__ko_mapping__":{"ignore":[],"include":["_destroy"],"copy":[],"observe":[],"mappedProperties":{"Profile.Id":true,"Profile.Name":true,"Profile.IsOutlet":true,"Profile.IsWholesaler":true,"Profile.IsProducer":true,"Profile.Localizations":true,"Profile":true,"LanguageCode":true,"Description":true},"copiedProperties":{}}}
Which gets parsed by Chrome like:
And on the server, when I try to receive a ProfileLocalizationViewModel, the values received are all null:
Any idea why this happens? Any advice greatly appreciated.
Client ajax call:
self.saveProfile = function (model, event) {
model.ItemForEditing.LanguageCode = self.SelectedLanguage.Code().toLowerCase();
var preview = ko.toJSON(model.ItemForEditing);
if (validateForm()) {
$.ajax({
type: "POST",
url: urlSaveProfile,
data: ko.toJSON(model.ItemForEditing),
contentType: 'application/json',
async: true,
beforeSend: function ()
success: function (result) {
// Handle the response here.
self.pushProfile(ko.mapping.fromJS(result.Data));
addContainer.modal('hide');
}
});
}
};
And inside preview, right before the call, there's the JSON...

C# Post Json String to Entity Model

I am trying to post a Json string, deserialize it, and then save it to a SQL database using MVC entity framework. Here is my model:
[Serializable]
public partial class employee
{
public int id { get; set; }
public string netid { get; set; }
public string enumber { get; set; }
public string peoplesoft { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string mi { get; set; }
public string prefix { get; set; }
public string suffix { get; set; }
public string email { get; set; }
public string tenure_year { get; set; }
public byte tenure_indicator { get; set; }
public Nullable<System.DateTime> hire_date { get; set; }
public string updated_by { get; set; }
public System.DateTime created_at { get; set; }
public System.DateTime updated_at { get; set; }
public string gender { get; set; }
public Nullable<System.DateTime> birth_date { get; set; }
}
My controller:
[HttpPost]
public ActionResult Create(ChadAPI.Models.Lookup.employee employee)
{
if (ModelState.IsValid)
{
db.employees.Add(employee);
db.SaveChanges();
return new JsonResult() { Data = employee, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
return Content("Model State Invalid");
}
And My View:
#model ChadAPI.Models.Lookup.employee
#{
ViewBag.Title = "Create";
}
<script src="~/Scripts/jquery-1.10.2.intellisense.js"></script>
<h2>Create</h2>
<input type="submit" id="Save" value="Save" />
<script>
$(function () {
$("#Save").click(function () {
alert("clicked!");
var employee = {
id: 77,
netid: 'caw63231',
enumber: '00000',
peoplesoft: '1012481',
firstname: 'Christian',
updatedby: 'caw63231',
createdat: '10/14/2013 3:02:46 PM',
updatedat: '10/14/2013 3:02:46 PM'
}
$.ajax({
type: "POST",
url: "Employees/Create",
data: employee,
success: function (data) {
console.log("success!")
},
dataType: "json",
traditional: true
});
});
});
</script>
When I press the button in the view nothing happens, and using Fiddler I can see that no JSON is passed whatsoever. What am I doing wrong?
MVC will automatically map the JSON request to your Actions parameters. The action you have written will be expecting a string object and you are trying to post it a JSON object containing an array.
You should update your action to receive an Employee object and post a JSON representation of this to the action. Like so:
$(function () {
$("#Save").click(function () {
var employee = {
id: 77,
netid : 'cfw22511',
enumber : '000000',
peoplesoft : '2322381'
//..... Add the rest of your data to the JSON object
};
$.ajax({
type: "POST",
url: "/Employees/Create",
data: employee,
success: function(data){
alert(data.Result)
},
dataType: "json",
traditional: true
});
});
});
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateChadAPI.Models.Lookup.employee employee)
{
if (ModelState.IsValid)
{
db.employees.Add(employee);
db.SaveChanges();
db.SaveChanges();
return new JsonResult() {Data = employee, JsonRequestBehavior = JsonRequestBehavior.AllowGet};
}
return Content("Model State Invalid");
}
Json is an object parsed as string, when sending this object to the server, MVC automatically convert it to the object, you don't have to do this by your self, so:
public ActionResult Create(ChadAPI.Models.Lookup.employee jsonemployee)
on the other side, create the same object' in Js:
var emp=new Object()
{
id:777,
}
also, check if your javascript code is running

Trouble with Knockout JSON Model parsing MVC 4 Controller

So I have a ViewModel:
public class PrelimViewModel
{
public int? PrelimId { get; set; }
public int JobId { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public string Comment { get; set; }
public string Unit { get; set; }
public int? Qty { get; set; }
public decimal? BidPrice { get; set; }
public bool Accepted { get; set; }
public int? OriginalPrelimId { get; set; }
public string Option { get; set; }
public List<RefCodeViewModel> Codes { get; set; }
public List<UnitViewModel> Units { get; set; }
public List<OptionLetterViewModel> Options { get; set; }
}
A GetPrelim controller method that returns List<PrelimViewModel>
A ko.mapper of the List of PrelimViewModel client side:
viewModel = ko.mapping.fromJS({ Prelims: data });
ko.applyBindings(viewModel);
Do some work, ready to save:
function savePrelims(elem) {
var $form = $(elem).parents('form');
$.ajax({
url: $form.attr('action'),
type: "POST",
data: ko.toJSON(viewModel),
datatype: "json",
contentType: "application/json charset=utf-8",
success: function(data) { toastr.success('Options Saved!'); },
error: function(data) { }
});
}
And I cannot get my MVC Method to parse the JSON:
public void AddPrelims(List<PrelimViewModel> Prelims)
You have wrapped your list into the Prelims property in your KO viewmodel, but on the server side you are expecting just a list not with an object which has the list in its Prelims property.
So to fix this you just need to send the list in your ajax request:
data: ko.toJSON(viewModel.Prelims()),
However you don't necessary need to wrap your list if you won't have any additional properties on your viewmodel, because you can just do:
viewModel = ko.mapping.fromJS(data);
ko.applyBindings(viewModel);
And then in your view you can bind to $data which is refering the current viewmodel which will be your array:
<div data-bind="foreach: $data">
...
</div>
And in this case you don't have to change your ajax call and data: ko.toJSON(viewModel), should work fine.
However this foreach: $data is kinda strange and it is not the best solution so you are probably better if you stick to your original approach with ko.mapping.fromJS({ Prelims: data }); and sending the correct data back to your controller.

Categories

Resources