Properties of class parameter are always null in Asp.Net Web Api - asp.net

In my web api controller there is an action method like below
[HttpPost]
[EnableCors(origins: "*", headers: "*", methods: "*", exposedHeaders: "X-Custom-Header")]
public IReportOutput InsuranceHandlingFiles([FromBody]CaseCountsInputData caseCountsInputData)
{
}
Parameter class of this action is
[Serializable]
public class CaseCountsInputData
{
public string MainTitle { get; set; }
public string YearTitle { get; set; }
public string InsurerFileCountTitle { get; set; }
public List<FileCount> FileCounts { get; set; }
public int InsurerTotalCount { get; set; }
public int GrandTotal { get; set; }
public string TotalTitle { get; set; }
public string GrandTotalTitle { get; set; }
}
[Serializable]
public class FileCount
{
public string year { get; set; }
public int InsurerFilesCount { get; set; }
}
I call this API method for testing purposes as follows. My action is called this way and my json object is binded to CaseCountsInputData class but all parameters are null. Can you help me exactly where I made the mistake?
$("#btnExport")
.click(function() {
var reportData = GetReportData();
console.log(JSON.stringify(reportData));
$.ajax({
type: "POST",
dataType: "json",
data: JSON.stringify(reportData),
contentType: "application/json",
url: "http://localhost:50773/api/export/insurancehandlingfiles",
success: function(data) {
var DocumentBody = data.Data;
var FileName = data.FileName;
dataURItoBlob(DocumentBody, FileName);
},
error: function(error,as,asd) {
jsonValue = jQuery.parseJSON(error.responseText);
alert("error" + error.responseText);
}
});
});
});
function GetReportData() {
var reportModel = {
CaseCountsInputData: {
MainTitle: "Dosya Sayısı",
YearTitle: "Yıl",
InsurerFileCountTitle: "Sigortacı Dosya Sayısı",
TotalTitle: "Toplam",
GrandTotalTitle: "Genel Toplam",
InsurerTotalCount: 1,
GrandTotal: 3,
FileCounts: []
}
}
var caseCounts =[];
caseCounts.push({
"year": 2014,
"InsurerFilesCount": 1
});
caseCounts.push({
"year": 2015,
"InsurerFilesCount": 4
});
for (var i = 0; i < caseCounts.length; i++) {
reportModel.CaseCountsInputData.FileCounts.push(caseCounts[i]);
}
return reportModel;
}

Related

ASP.NET Core 5 MVC : post model binding complex collection back to controller instantiates vm but without data

I'm trying to post back a complex collection (POCOs) to my controller. The array created by serializeArray() looks good to me (but maybe it is not).
I tried conforming my code in this project to code that works in an ASP.NET Core 5 MVC & EF 6 project I have. Something has changed since then. Can't figure out what I am missing.
Here's my current version of the Ajax call:
$('#btnCreate').click(function(e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '#Url.Action("CreatePL", "Reports")',
data: JSON.stringify({ glassDemands: $('#plTarget').serializeArray() }),
contentType: 'application/json; charset=UTF-8',
success: function(data) {
},
error: function(xhr) {
}
});
});
Here's a screenshot of the first several lines of data it creates:
This screenshot shows the action in the controller with result from post:
Here are the three classes that make up the view. Microsoft documentation states that
POCOs that do not have parameterless constructors can't be bound.
Code:
public class GlassDemand
{
public GlassDemand()
{
Boxes = new HashSet<Box>();
}
public string bunk { get; set; }
public int sequence { get; set; }
public string tag { get; set; }
public string elevation { get; set; }
[Display(Name = "Glass")]
public string glasstag { get; set; }
[Display(Name = "Needed")]
public int glassqty { get; set; }
// total quantity selected from boxes. should be the sum of all related boxitem.usedqty
[NotMapped]
[Display(Name = "Sel Qty")]
public int pickedqty { get; set; }
[NotMapped]
public ICollection<Box> Boxes { get; set; }
[NotMapped]
public int ItemId { get; set; }
}
public class Box
{
public int BoxId { get; set; }
public string Name { get; set; }
public bool Selected { get; set; }
public string Location { get; set; }
public virtual ICollection<BoxItem> BoxItems { get; set; }
public int MatchedTo { get; set; }
public Box()
{
BoxItems = new HashSet<BoxItem>();
}
}
public class BoxItem
{
public BoxItem()
{
}
public int ItemId { get; set; }
public string Name { get; set; }
[DisplayFormat(DataFormatString = "{0:N0}")]
public decimal Qty { get; set; }
public int BoxId { get; set; }
public int UsedById { get; set; }
[DisplayFormat(DataFormatString = "{0:N0}")]
public decimal UsedQty { get; set; }
// remaining = Qty (box quantity) - sum(UsedQty from all instances)
[DisplayFormat(DataFormatString = "{0:N0}" )]
public decimal Remaining { get; set; }
// navigations
public virtual Box Box { get; set; }
}
And the view model that is sent to the view when it is launched.
public class PickListDemandVM
{
public IEnumerable<GlassDemand> GlassDemands { get; set; }
public PickListDemandVM()
{
GlassDemands = new List<GlassDemand>();
}
}
.serializeArray() is used to post application/x-www-url-formencoded content type data to backend.Change your code like below:
$('#btnCreate').click(function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '#Url.Action("CreatePL", "Reports")',
data: $('#plTarget').serializeArray() ,
//contentType: 'application/json; charset=UTF-8',
success: function(data) {
},
error: function(xhr) {
}
});
});
Remove [FromBody] in Controller:
[HttpPost]
public ActionResult CreatePL(List<GlassDemand> glassDemands)
I don't understand all the nuances of model bindings. One thing is for sure though, you have to have keys on all tables being posted. With proper keys in place, I can use a view model or a List<> parameter in my controller action. From MS documentation, using a view model is the preferred method.
My POCOs didn't have keys. I ended up using a counter while I built my data on the highest level table, GlassDemand. Then built increasingly more complex keys for each descendent.
I added the following to my classes to hold the values that are dynamically being created for their respective tables.
[Key]
public string Id { get; set; }
I added this line to my display templates
#Html.HiddenFor(model => model.Id)
This is the first two rows look like that is being posted back to the controller now.
My dataset was also too large. I had to add the following attribute to the controller action. Thanks to DAustin's post
[RequestFormLimits(ValueCountLimit = 10000)]
the final jquery that posts back the data:
$('#btnCreate').click(function(e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '#Url.Action("CreatePL", "Reports")',
data: $('#plTarget').serializeArray(),
success: function(data) {
},
error: function(xhr) {
}
});
});
the final action in the controller:
[HttpPost]
[RequestFormLimits(ValueCountLimit = 10000)]
public ActionResult CreatePL(PickListDemandVM vm)
{

How to consume .Net webservice in angular post method?

how to call post method in angular 5 and ionic 3.
My angular code is:
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
let body= {
records:
this.records
};
this.http.post('http://localhost:13799/HealthPotliWebService.asmx/getsingleproductdetails',
"{body2:" + JSON.stringify(body) + "}",options)
.map(res=>res.json())
.subscribe(data=>{
console.log(data);
});
}
this is my webservice class
my class is like this :
public class body2
{
public List<records> records { get; set; }
}
public class records
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public string Description { get; set; }
}
webservice code :
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string getsingleproductdetails(body2 body2)
{
// some code here
return new JavaScriptSerializer().Serialize(resources);
}
Return type of my webservice is:
<string xmlns="http://tempuri.org/">
{"error_msg":"Success","status":"0","medicinename":"CROCIN","description":"\u003cdiv style=\u0027text-align:justify;\u0027\u003e\u003cu\u003e\u003cb\u003eParacetamol\u003c/b\u003e\u003c/u\u003e-\u003cu\u003e125mg\u003c/u\u003e\u003cbr/\u003e\u003cbr/\u003e\u003c/div\u003e","lstComments":[],"rateValue":0,"potliMoney":0,"offer":null}
</string>

WCF DeSerialize form-urlencode data into Class Object

I want to DeserializeObject of x-www-form-urlencoded string
public void TestData1(Stream data)
{
StreamReader sr = new StreamReader(data);
string strJson = sr.ReadToEnd();
var response = Newtonsoft.Json.JsonConvert.DeserializeObject<Recipe>strJson);
}
Below is my Request application/x-www-form-urlencoded
title=test&recipe_accessories=%5B+++++%7B+++++%22accessories_id%22%3A%22ingr001%22+++++++%7D%2C++++++%7B+++++%22ingredient_id%22%3A%22ingr001%22+++++%7D%2C++++++%7B+++++%22ingredient_id%22%3A%22ingr001%22+++++%7D+++%5D&recipe_ingredient=%5B+++++%7B+++++%22ingredient_id%22%3A%22ingr001%22%2C+++++%22ingredient_qty_num%22%3A%222.5%22%2C+++++%22ingredient_qty_unit%22%3A%22cup%22++++++++++++%7D%2C++++++%7B+++++%22ingredient_id%22%3A%22ingr001%22%2C+++++%22ingredient_qty_num%22%3A%222.5%22%2C+++++%22ingredient_qty_unit%22%3A%22cup%22++++++++++++%7D%2C++++++%7B+++++%22ingredient_id%22%3A%22ingr001%22%2C+++++%22ingredient_qty_num%22%3A%222.5%22%2C+++++%22ingredient_qty_unit%22%3A%22cup%22++++++++++++%7D+++%5D&recipe_img=%5B+++++%22http%3A%2F%2Fcontrol%2Fimages%2Ftest.jpg%22%2C+++++%22http%3A%2F%2Fcontrol%2Fimages%2Ftest.jpg%22%2C+++++%22http%3A%2F%2Fcontrol%2Fimages%2Ftest.jpg%22%2C+++++%22http%3A%2F%2Fcontrol%2Fimages%2Ftest.jpg%22%2C+++++%22http%3A%2F%2Fcontrol%2Fimages%2Ftest.jpg%22+++%5D
Error
Error parsing boolean value. Path '', line 1, position 1.'. See server logs for more details. The exception stack trace is: at Json.JsonTextReader.ParseTrue()
Actual Json in Raw format
{
"recipe_img": [
"http://control/images/test.jpg",
"http://control/images/test.jpg",
"http://control/images/test.jpg",
"http://control/images/test.jpg",
"http://control/images/test.jpg"
],
"recipe_ingredient": [
{
"ingredient_id":"ingr001",
"ingredient_qty_num":"2.5",
"ingredient_qty_unit":"cup"
},
{
"ingredient_id":"ingr001",
"ingredient_qty_num":"2.5",
"ingredient_qty_unit":"cup"
},
{
"ingredient_id":"ingr001",
"ingredient_qty_num":"2.5",
"ingredient_qty_unit":"cup"
}
],
"recipe_accessories": [
{
"accessories_id":"ingr001"
},
{
"ingredient_id":"ingr001"
},
{
"ingredient_id":"ingr001"
}
],
"title": "Hello WOrld",
}
When I use the BodyStyle = WebMessageBodyStyle.Bare and pass the Json in RAW format it works fine.
It will not work when the BodyStyle = WebMessageBodyStyle.WrappedRequest
Here is my Class
public class Recipe
{
public IList<string> recipe_img { get; set; }
public IList<RecipeIngredient> recipe_ingredient { get; set; }
public IList<RecipeAccessory> recipe_accessories { get; set; }
public string title { get; set; }
}
public class RecipeIngredient
{
public string ingredient_id { get; set; }
public string ingredient_qty_num { get; set; }
public string ingredient_qty_unit { get; set; }
}
public class RecipeAccessory
{
public string accessories_id { get; set; }
public string ingredient_id { get; set; }
}

ASP.NET Cannot get FULL list of ALL countries in the world

There are 196 countries in the world.
I'm trying to show a dropdown list that show all of them.
I see many developer suggest using CultureInfo of ASP.NET but it's missing some countries because Culture & Country are different things.
So how can I get a list of all countries for my purpose please ?. I really appreciate your help.
In ASP.NET a DropDown
<asp:DropDownList ID="selCountries" runat="server"></asp:DropDownList>
is equivalent to
<select id="selCountries"></select>
Alternatively, you could use a Web service to fill a select tag with countries through JavaScript XMLHttpRequest object.
Example: https://restcountries.eu/
Something like this:
(function() {
var newXHR;
function sendXHR(options) { // Helper function.
newXHR = new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP");
if (options.sendJSON === true) {
options.contentType = "application/json; charset=utf-8";
options.data = JSON.stringify(options.data);
} else {
options.contentType = "application/x-www-form-urlencoded";
}
newXHR.open(options.type, options.url, options.async || true);
newXHR.setRequestHeader("Content-Type", options.contentType);
newXHR.send((options.type == "POST") ? options.data : null);
newXHR.onreadystatechange = options.callback;
return newXHR;
}
sendXHR({
type: "GET",
url: "https://restcountries.eu/rest/v1/all",
callback: function() {
if (newXHR.readyState === 4 && newXHR.status === 200) {
var data = JSON.parse(newXHR.response);
var selCountries = document.getElementById("selCountries"); // Get the select tag.
// You can get the selected country.
selCountries.onchange = function() {
alert(this.value);
};
var option;
for (var i = 0; i < data.length; i++) { // For every country make an option tag.
option = document.createElement("option");
selCountries.options.add(option, 0);
selCountries.options[0].value = data[i].name; // Country name from the index «i» of the data array.
selCountries.options[0].innerText = data[i].name;
selCountries.appendChild(option); // Append the option tag to the select tag.
}
}
}
});
})();
<select id="selCountries"></select>
In ASP.NET MVC5 NET 4.5, you can bind an object to #Html.DropDownList by using ViewBag.
You need to create a model according to https://restcountries.eu/rest/v1/all json response.
Model: CountryModel.cs
using System.Collections.Generic;
namespace RestCountries.Models
{
public class Translations
{
public string de { get; set; }
public string es { get; set; }
public string fr { get; set; }
public string ja { get; set; }
public string it { get; set; }
}
public class CountryModel
{
public string name { get; set; }
public string capital { get; set; }
public List<string> altSpellings { get; set; }
public string relevance { get; set; }
public string region { get; set; }
public string subregion { get; set; }
public Translations translations { get; set; }
public int population { get; set; }
public List<object> latlng { get; set; }
public string demonym { get; set; }
public double? area { get; set; }
public double? gini { get; set; }
public List<string> timezones { get; set; }
public List<object> borders { get; set; }
public string nativeName { get; set; }
public List<string> callingCodes { get; set; }
public List<string> topLevelDomain { get; set; }
public string alpha2Code { get; set; }
public string alpha3Code { get; set; }
public List<string> currencies { get; set; }
public List<object> languages { get; set; }
}
}
Controller: DefaultController.cs
using RestCountries.Models;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web.Mvc;
namespace RestCountries.Controllers
{
public class DefaultController : Controller
{
// GET: Default
public ActionResult Index()
{
string url = "https://restcountries.eu/rest/v1/all";
// Web Request with the given url.
WebRequest request = WebRequest.Create(url);
request.Credentials = CredentialCache.DefaultCredentials;
WebResponse response = request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string jsonResponse = null;
// Store the json response into jsonResponse variable.
jsonResponse = reader.ReadLine();
if (jsonResponse != null)
{
// Deserialize the jsonRespose object to the CountryModel. You're getting a JSON array [].
List<CountryModel> countryModel = Newtonsoft.Json.JsonConvert.DeserializeObject<List<CountryModel>>(jsonResponse);
// Set the List Item with the countries.
IEnumerable<SelectListItem> countries = countryModel.Select(x => new SelectListItem() { Value = x.name, Text = x.name });
// Create a ViewBag property with the final content.
ViewBag.Countries = countries;
}
return View();
}
}
}
View: Index.cshtml
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#Html.DropDownList("Countries")
Result:

How to send a list of class from client into webmethod with ajax

I have a list of class that made in client with typescript, Now i want to send it to webmethod.
My typescript code is below :
class MakeReportData {
LocalName: string;
FldSi: number;
ViewSi:number;
TypeName:string ;
CheckBoxshow :boolean ;
CheckBoxFilter:boolean;
}
My Ajax code is below :
var temp: MakeReportData[] = [];
for (var i = 0; i < $scope.myData.ReportDetail.length; i++) {
var rep: MakeReportData=new MakeReportData();
rep.LocalName = $scope.myData.ReportDetail[i].LocalName;
rep.FldSi = $scope.myData.ReportDetail[i].FldSi;
rep.ViewSi = $scope.myData.ReportDetail[i].ViewSi;
rep.TypeName = $scope.myData.ReportDetail[i].TypeName;
rep.CheckBoxshow = $scope.myData.ReportDetail[i].CheckBoxshow;
rep.CheckBoxFilter = $scope.myData.ReportDetail[i].CheckBoxFilter;
temp.push(rep);
}
var tedata = JSON.stringify({ itm: temp });
alert(tedata);
$.ajax({
type: "POST",
url: "MakeReport.aspx/GetList",
contentType: "application/json; charset=utf-8",
data: tedata ,
dataType: "json",
success: function (data) {
alert(data.d);
},
error: function (data, status, jqXHR) {
alert(status);
alert(jqXHR);
}
});
my webmethod is below :
[WebMethod]
public static string GetList(MakeReportData[] itm)
{
return "";
}
my class in C# is like this :
public class MakeReportData
{
public string LocalName { get; set; }
public int FldSi { get; set; }
public int ViewSi { get; set; }
public string TypeName { get; set; }
public bool CheckBoxshow { get; set; }
public bool CheckBoxFilter { get; set; }
}
I want to send the list of MakeReportData to the server webmethod.
My problem is that the webmethod does not call.
I made it myself, It just need to make webmethod's input as list like below:
public static string GetList(List<MakeReportData> itm)
{
return "";
}

Resources