How to deserialize multiple JSON objects in C#? - javascript

I'm passing multiple JSON objects from my frontend to a C# backend - how can I deserialize them into C# classes so they can be used later on in my application? Before I go any farther, I am tied to using the JS FormData object, contentType: false, and processData: false, because I also need to pass files via this AJAX call; that is completely unrelated to this question. Here's my code so far:
Frontend - function is called when a submit button is pressed
submitData: function () {
var formCollection = this.appModel.get('formCollection').models;
var formData = new FormData();
var formJson = [];
$.each(formCollection, function (index, form) {
var tempJson = {};
if (form) {
tempJson['id'] = form.get('id');
tempJson['number'] = form.get('number');
tempJson['name'] = form.get('name');
tempJson['attachments'] = form.get('attachments');
formJson.push(tempJson);
}
});
console.log(JSON.stringify(formJson));
formData.append('formJson', JSON.stringify(formJson));
$.ajax({
type: "POST",
url: '/NMISProduct/Test',
contentType: false,
processData: false,
data: formData,
success: function (result) {
console.log(result);
}
});
}
JSON.stringified data that's being passed
[{"id":1,"number":null,"name":"Investment Portfolio Statement","attachments":null},{"id":2,"number":"61-0227","name":"WMC Signature Portfolio Agreement","attachments":null},{"id":3,"number":"61-1126","name":"WMC Signature Choice Agreement","attachments":null},{"id":4,"number":"61-1162","name":"WMC Signature Annuities Agreement","attachments":null},{"id":5,"number":"61-1205","name":"WMC Signature Managed Accounts Client Agreement","attachments":null}]
C# MVC 5 Backend
[HttpPost]
public async Task<JsonResult> Test()
{
Debug.WriteLine(Request.Params["formJson"]);
var forms = JsonConvert.DeserializeObject<Form>(Request.Params["formJson"]);
Debug.WriteLine(forms);
try
{
var srNumber = GetSRNumber();
foreach (string file in Request.Files)
{
var fileContent = Request.Files[file];
Debug.WriteLine(ReadFileInputStream(fileContent));
if (fileContent != null && fileContent.ContentLength > 0)
{
// get a stream
var stream = fileContent.InputStream;
// and optionally write the file to disk
//var fileName = Path.GetFileName(file);
var fileName = fileContent.FileName;
var path = Path.Combine(Server.MapPath("~/App_Data/"), fileName);
using (var fileStream = System.IO.File.Create(path))
{
stream.CopyTo(fileStream);
}
}
}
}
catch (Exception)
{
return Json("Upload failed");
}
return Json("File uploaded successfully");
}
public class Form
{
public int id { get; set; }
public string number { get; set; }
public string name { get; set; }
public Form attachments { get; set; }
public byte[] fileAsBytes { get; set; }
}
I've done my research and found several Stackoverflow questions that show how to serialize one JSON object into one C# class - however, I need to serialize multiple JSON objects into a List<Form>. How can I do this? What am I doing wrong in the posted code?

You're trying to deserialize to a single form here:
var forms = JsonConvert.DeserializeObject<Form>(Request.Params["formJson"]);
Just change it to:
var forms = JsonConvert.DeserializeObject<List<Form>>(Request.Params["formJson"]);
You should then be able to use forms in a normal way - iterating over it, taking a count etc.

[HttpPost]
public async Task<JsonResult> Test(List<Form> forms)
{
// your code here
}
And put your JS code
formJson.push(tempJson);
inside the
if (form)

Related

Can't pass array of objects to controller by jQuery AJAX

I tried to pass array of objects to controller by jQuery Ajax, but result is null in ASP.NET 5.0.
My data array is what send to controller: regions.
Data constructor is defined in BoundingBoxModel class.
This is my ajax function:
$("body").on("click", "#onClick", function () {
var regions = [];
var arr = Array.prototype.slice.call(document.getElementsByClassName('ui-draggable'));
arr.forEach((tagele) => {
var region = {};
region.Height = tagele.offsetHeight;
region.Width = tagele.offsetWidth;
region.Top = tagele.offsetTop;
region.Left = tagele.offsetLeft;
regions.push(region);
});
$.ajax({
url: '/GenCode/Addregions',
type: "POST",
dataType: "json",
contentType: "application/json;charset=utf-8",
data: JSON.stringify({'regions': regions}),
success: function () {
alert("pass")
},
error: function (jqXhr, json, errorThrown) {
alert(errorThrown);
console.log(errorThrown);
}
});
});
So this is my BoundingBoxModel:
public class BoundingBoxModel
{
public int BoundingBoxId { get; set; }
public double Top { get; set; }
public double Left { get; set; }
public double Height { get; set; }
public double Width { get; set; }
}
This is my action method. It's defined in GenCodeController.
[HttpPost]
public IActionResult AddRegions(List<BoundingBoxModel> regions)
{
JsonResult result = new JsonResult(this.Json(JsonConvert.SerializeObject(regions), System.Web.Mvc.JsonRequestBehavior.AllowGet));
return result;
}
My result is null:
I don't understand why it's happened. Can you help me?
There are some issues that I can see -
I am not sure if you explicitly written this logic but your region object will always have last value of arr because you declare your variable inside loop.
If you are trying to create an array then you should declare your region variable like - var region = []; .Right now it is an object.
You are trying to pass an object and accepting a list in webservice. Either remove the list in parameter in AddRegions service or pass a Array from ajax call.
I resolved my problem by deteting contentType: "application/json;charset=utf-8", line in ajax code.
Using this line make the array of region's type change to string so when i get data in Controller problem was happened.

Post knockout.js viewmodel to .Net Core (2.0) MVC Controller

Overview:
Currently, I try to create an ASP.NET Core MVC website which gets data from the server on page load. After that, the page uses knockout.js to maintain a viewmodel to update the data sent from the server (in the first step). Finally, there is a button which sends the edited data back to the server (through an AJAX request). But the corresponding value in my server method is always empty.
Current Approach:
First, there is my model class.
public class Order
{
public string Name { get; set; }
public int TemplateId { get; set; }
public decimal Price { get; set; }
public int Contingent { get; set; }
public int MaximumOrder { get; set; }
public int UserOrderCount { get; set; }
public Order() { }
public Order(SnackOffer offer)
{
Name = offer.Template.Name;
TemplateId = offer.Template.SnackTemplateId;
Price = offer.Price;
}
}
In my view I use the model class as a List (List) and load the data like this:
var model = new viewModel();
#(Json.Serialize(Model.Offers)).forEach(function (item, index) {
model.offers.push({
name: item.name,
templateId: item.templateId,
contingent: ko.observable(item.contingent),
userOrderCount: ko.observable(item.userOrderCount),
price: item.price,
maximumOrder: item.maximumOrder
});
})
The viewModel is defined like this (shortend for readability):
function viewModel() {
var self = this;
self.offers = ko.observableArray();
}
Now after someone hits the mentioned update button I call this javascript function:
self.ConfirmOrder = function () {
var data = ko.toJSON(self.offers);
$('#overlay').css('display', 'block');
$.ajax({
type: 'post',
url: '/Snack/ConfirmOrder',
data: data,
contentType: 'application/json; charset=utf-8',
success: function (result) {
$('#overlay').css('display', 'none');
},
error: function (result) {
console.log(result);
$('#overlay').css('display', 'none');
}
});
}
Here you can see that I use the ko.toJSON method to convert the observableArray to a JSON String and use this string as the data argument for the ajax post.
The ConfirmOrder method in the MVC Controller looks like this currently:
[HttpPost]
public void ConfirmOrder(List<OrderSnackViewModel.Order> offers)
{
foreach (var item in offers)
{
_logger.LogInformation(item.Name);
}
}
There is no logic yet cause the offers list is created (so not null) but the count of list items is always 0.
In a concret example this is the JSON string I receive from the server while load the view:
[{"name":"Test","templateId":1,"price":1.94,"contingent":4,"maximumOrder":7,"userOrderCount":0},{"name":"Test 1","templateId":2,"price":1.50,"contingent":30,"maximumOrder":7,"userOrderCount":0}]
And this is the string i produce with the ajax call:
[{"name":"Test","templateId":1,"contingent":4,"userOrderCount":0,"price":1.94,"maximumOrder":7},{"name":"Test 1","templateId":2,"contingent":30,"userOrderCount":0,"price":1.5,"maximumOrder":7}]
What have I tried already:
I have tried to use FromBody in my MVC Controller
I have tried to prefix the JSON output with the name offer so my controller method can map the JSON string items to the object. (e.g. data = '{ "offers":' + data + '}'; )
I have tried to rename the Properties of my model to match exactly the JSON names. So I renamed Name to name and Contingent to contingent and so on.
I have tried to use an array instead of the List in the MVC controller action
Is there a master somewhere which can help me with this problem?
(If you need some more information please do not hesitate to ask)
Thanks to the input of #adiga I have found the solutions for (my) error.
[HttpPost]
public JsonResult ConfirmOrder([FromBody]List<Order> offers)
{
_logger.LogInformation("COUNT -> " + offers.Count());
foreach (var item in offers)
{
_logger.LogInformation(item.Name);
}
}
This is the working solution. I thought I already have tried it but maybe I have forgoten the content-type for the ajax post.
var data = ko.toJSON(self.offers);
$('#overlay').css('display', 'block');
$.ajax({
type: 'post',
url: '/Snack/ConfirmOrder',
data: data,
contentType: 'application/json; charset=utf-8',
success: function (result) {
//location.reload();
$('#overlay').css('display', 'none');
},
error: function (result) {
console.log(result);
$('#overlay').css('display', 'none');
}
});
Thanks again for all responses!

data is saved but post request is failed when and give server error

I try to save fields by action controller action method which return different view. But failed to do this: My Jquery code is:
$("#btnAdd").click(function () {
var Product = {
name: $("#txtProductName").val(),
color: $("#ddlColor option:selected").val(),
gage: $("#ddlGage option:selected").val(),
rate: $("#txtrate").val()
};
$.ajax({
});
$.post("ProductTable", { Pro: JSON.stringify(Product) }, function (data) {
$("#RightDiv").html(data);
alert(data);
});
});
and my controller action method on the same controller which return different view:
public ActionResult ProductTable()
{
Product product = new Product();
JavaScriptSerializer serializer = new JavaScriptSerializer();
product = serializer.Deserialize<Product>(Request.Form["Pro"]);
productDB.addProduct(product);
productManager.productTable = productDB.getAllProducts();
return View(productManager);
}
Browser give me error:
HTTP500: SERVER ERROR - The server encountered an unexpected condition that prevented it from fulfilling the request.
(XHR)POST - http://localhost:59008/Product/ProductTable
If you're using MVC, it should handle the serialization/deserialization for you. You just need to make sure the object sent over matches the object you declare in MVC controller action parameter.
Client-side
// Suggestions:
// * use camelCase for javascript variables and functions
// * jQuery .val() on selects should give you the selected value
// * always use fully qualified Url generated by Html.Helper
$("#btnAdd").click(function () {
var product = {
name: $("#txtProductName").val(),
color: $("#ddlColor").val(),
gage: $("#ddlGage").val(),
rate: $("#txtrate").val()
};
var createUrl = '#Url.Action("create", "product", new { area = "" })';
$.post(createUrl, product, function (response) {
$("#RightDiv").html(response);
alert(response);
});
});
Server-side
// Suggestions:
// * NEVER send your domain model back to the page! You should create
// a ViewModel to just include what you want to show the users
[HttpPost]
public ActionResult Create(CreateProductViewModel model)
{
...
productDB.addProduct(new Product {
Name = model.Name,
Color = model.Color,
Gage = model.Gage,
Rate = model.Rate,
// And other stuff like
// CreatedBy = User.Identity.Name
});
// This looks weird to me too!
productManager.productTable = productDB.getAllProducts();
return View(productManager);
}
The ViewModel
public class CreateProductViewModel
{
public string Name { get; set; }
public int Color { get; set; }
public int Gage { get; set; }
public double Rate { get; set; }
}

My controller don't receive the IDs of an AJAX request

I have a JavaScript function that uses AJAX request to send data to my controller on asp.net MVC. Look:
function verCarrinho() {
$.ajax({
type: "POST",
url: "/Produto/Carrinho",
data: { "carrinho": carrinho },
success: function (e) {
}
});
}
Where carrinho is an array with two properties. One of these properties is an ID that I need to send to my controller to use EF to make a query on my data base.
My ActioNResult on controller:
[HttpPost]
public ActionResult Carrinho(List<Carrinho> carrinho)
{
var ids = carrinho.Select(s => s.idLivro).ToList();
var resultado = db.Produtos.Where(w => ids.Contains(w.idProduto));
return PartialView("_Carrinho", resultado);
}
The problem is: my variable "resultado" stay null! The AJAX is not sending the IDs. If I put a breakpoint on resultado I can see that AJAX send the objects, but I can't see the IDs.
I have a class same type of my parameter:
public class Carrinho
{
public int idLivro;
public int qtdProduto;
}
I don't know if I could be clear, but I hope you can help.
Thank you.
you need to data: JSON.stringify({ "carrinho": carrinho }) and also add contentType: 'application/json; charset=utf-8', to ajax call.
Javascript Object Literal Syntax !== JSON.
You need to JSON.stringify() your data object in your ajax request.
I changed my code based on a friend's code and it works. It's look like this:
namespace WebAppImaginario.Models
{
public class ItemCarrinho
{
public int idLivro { get; set; }
[DisplayName("Quantidade do Produto")]
public int qtdProduto { get; set; }
[DisplayName("Nome do Produto")]
public string nomeProduto { get; set; }
[DisplayName("Descrição do Produto")]
public string descProduto { get; set; }
[DisplayName("Preço do Produto")]
public decimal precProduto { get; set; }
[DisplayName("Desconto da Promoção")]
public decimal descontoPromocao { get; set; }
[DisplayName("Imagem")]
public byte[] imagem { get; set; }
}
}
Controller:
[HttpPost]
public ActionResult Carrinho(string hidCarrinho)
{
List<ItemCarrinho> listaCarrinho = new List<ItemCarrinho>();
if (hidCarrinho != null)
{
var itens = JsonConvert.DeserializeObject<List<ItemCarrinho>>(hidCarrinho);
foreach (var item in itens)
{
var qtd = int.Parse(new string(item.qtdProduto.ToString().Where(char.IsDigit).ToArray()));
if (qtd > 0)
{
var idLivroNumerico = int.Parse(new string(item.idLivro.ToString().Where(char.IsDigit).ToArray()));
var resultado = db.Produtos.Where(m => m.idProduto == idLivroNumerico).FirstOrDefault();
ItemCarrinho prod = new ItemCarrinho();
prod.idLivro = idLivroNumerico;
prod.qtdProduto = qtd;
prod.nomeProduto = resultado.nomeProduto;
prod.descProduto = resultado.descProduto;
prod.precProduto = resultado.precProduto;
prod.descontoPromocao = resultado.descontoPromocao;
prod.imagem = resultado.imagem;
listaCarrinho.Add(prod);
}
}
}
return View(listaCarrinho);
}
JavaScript:
function setValueEnviar() {
$("#hiddenInputContainer").empty();
for (var i = 0; i < carrinho.length; i++) {
var newInput = document.createElement('input');
newInput.type = "hidden";
newInput.value = JSON.stringify(carrinho[i]);
newInput.name = 'data';
$("#hiddenInputContainer").append(newInput);
}
}
$('#formCarrinho').submit(function (e) {
e.preventDefault();
$('#hidCarrinho').val(JSON.stringify(carrinho));
document.formCarrinho.submit();
})
Those IDs are a form on my page and hidden input. I don't know if it is clear, but it works to me.
Thank you for all support.
Syntax like data: { "carrinho": carrinho } can work, $.ajax does accept a PlainObject as data (see http://api.jquery.com/jquery.ajax/).
Your problem is that your variable carrinho is not conforming to the requirements of a PlainObject.
The PlainObject type is a JavaScript object containing zero or more key-value pairs
http://api.jquery.com/Types/#PlainObject
Depending on what carrinho is, you may have success with stringify as an alternative:
function verCarrinho() {
$.ajax({
type: "POST",
url: "/Produto/Carrinho",
data: JSON.stringify({ "carrinho": carrinho }),
success: function (e) {
}
});
}

How to parse a JSON object ? (From server-side to client-side...javascript)

I have a jquery interacting with a server side Web Method. The Web method accepts a string 'memID' from the jquery and executes SQL queries based on it. Then I create a class:-
public class Member
{
// Objects of Member. //
public string id { get; set; }
public string HPCode { get; set; }
public string OPfromDate { get; set; }
public string OPthruDate { get; set; }
public Member(string ID, List<string> hpCode, List<string> opfromDate, List<string> opthruDate)
{
id = ID;
for (int j = 0; j < hpCode.Count; j++){ HPCode = HPCode + (hpCode)[j] + '*' };
for (int j = 0; j < opfromDate.Count; j++){OPfromDate = OPfromDate + (opfromDate)[j] + '*' };
for (int j = 0; j < opthruDate.Count; j++){OPthruDate = OPthruDate+ (opthruDate)[j] + '*' };
}
}
This class is used to return the results of my SQL query to the client side:-
return JsonConvert.SerializeObject(member);
I used breakpoints and checked on the client side, indeed it is getting the return values. However I am not sure about what is the best way to parse these values and store them in variables on my javascript side so i can use them for client-side functionalities.
// Ajax function that sends member ID from client side to server side without a post back.
function ajax()
{
$.ajax
({
url: 'Default.aspx/MyMethod',
type: 'POST',
dataType: "json",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ memID: mem_ID }),
success: onSuccess,
fail : onFail
});
}
// If client-to-server communication is successful.
function onSuccess(data)
{
confirm(data.d);
var returnedstring = (data.d);
var jsondata = $.parseJSON(data.d);
}
Now how do I parse the 'data' ?? is there an eval function? or parse function?
Does anybody have any web examples? before this I was only passing back 1 value to my client side, so it was easy to get, now i am confused with multiple values.
UPDATE:-
I tried doing this on my javascript side:-
var returnedstring = (data.d);
var member = data.d.id;
var Hp = data.d.HPCode;
however when I use breakpoints and hover over them with my mouse, i get member and HP as undefined, however the returnedstring has all the correct values.. ... any idea?
SOLUTION (I couldn't figure out the other way suggested in the answers, but this works for me) :-
function onSuccess(data)
{
// stores entire return in one string.
var returnedstring = (data.d);
// parses json returned data
var jsondata = $.parseJSON(data.d);
var member = jsondata.id;
var HpCode = jsondata.HPCode;
}
Because you're using dataType: "json", data is already parsed out of the JSON string. That's why you're able to access data.d in Javascript.
To access the members, you can do something like this:
console.log(data.d.HPCode);

Categories