Can not get a value of key-value pair using [FromBody] - javascript

Data is sent from front-end to back-end. Request body is created like this
var stateWithValue = {};
for (const item in self.pricings()) {
state[item] = self.pricings()[item]["Comment"];
}
var request = {
generalComment: self.generalComment(),
stateWithValue: stateWithValue
};
Request body looks like this
{
generalComment: "test comment",
stateWithValue:
{
Delaware: "Value1",
California: "Value2",
Texas: "Value3"
}
}
Number of elements in stateWithValue can be different for every request.
In the back-end, data is taken using [FromBody] attribute
public WebApiResponseGeneric<EmptyResponse> State([FromBody] StateRequest request)
StateRequest.cs
public class StateRequest : PublicRequest
{
public string GlobalComment { get; set; }
public StateWithValue StateWithValue { get; set; }
}
public class StateWithValue
{
public string State { get; set; }
public string Value { get; set; }
}
In network tab(dev console) payload looks like this
generalComment: test general comment
stateWithValue[Delaware]: Value1
stateWithValue[California]: Value2
stateWithValue[Texas]: Value3
The Problem
In back-end request object, StateWithValue.State StateWithValue.Value are both null.

YOu have to post PublicRequest class too. But for your request body json, your class should be
public class StateRequest : PublicRequest
{
public string generalComment{ get; set; }
public Dictionary<string, string> stateWithValue { get; set; }
}
or change
public class StateRequest : PublicRequest
{
public string GlobalComment { get; set; }
public List<StateWithValue> StateWithValue { get; set; }
}
and javascript
var stateWithValue = [];
for (const item in self.pricings()) {
var stateWithValueItem={};
stateWithValueItem.State =item;
stateWithValueItem.Value = self.pricings()[item]["Comment"];
stateWithValue.push(stateWithValueItem);
}

In order to map the JSON:
{
generalComment: "test comment",
stateWithValue:
{
Delaware: "Value1",
California: "Value2",
Texas: "Value3"
}
}
You would need to use the following C# model
public class StateRequest : PublicRequest
{
public string GeneralComment { get; set; }
public StateWithValue StateWithValue { get; set; }
}
public class StateWithValue
{
public string Dalaware { get; set; }
public string California { get; set; }
public string Texas { get; set; }
}
If you want to map multiple states then consider using an array instead, something like:
{
generalComment: "test comment",
stateWithValue:
[
State: "Delaware", Value: "Value1",
State: "California", Value: "Value2",
State: "Texas", Value: "Value3"
]
}
But your model would need to be updated to look something like this:
public class StateRequest : PublicRequest
{
public string GeneralComment { get; set; }
public List<StateWithValue> StatesWithValues { get; set; }
}
Note: There is a typo with general vs Global in your sample code

Related

Ajax .NET Core MVC send JSON Array to Controller using Ajax

I am trying to send my data in a table to Controller by Columns, but I have tried so many methods, the parameter table is always null. Could you please give some advise on this? Thanks
Front-end Code
var data = {
"Peril": histLossesTable.getDataAtCol(0),
"OccurrenceYear": histLossesTable.getDataAtCol(1),
"Month": histLossesTable.getDataAtCol(2),
"Event": histLossesTable.getDataAtCol(3),
"InsuredLoss": histLossesTable.getDataAtCol(4),
"UnderWriterYear": histLossesTable.getDataAtCol(6),
"ReturnPeriod": histLossesTable.getDataAtCol(5),
"SelectedIndex": histLossesTable.getDataAtCol(7),
"TrendedLoss": histLossesTable.getDataAtCol(8),
"ReportingThreshold": document.getElementById('reportingThreshold').value
};
console.log(JSON.stringify(data));
$.ajax({
type: "POST",
url: "/home/test",
dataType: "json",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
success: function (e) {
if (e.success == true) {
console.log('POST Successful');
}
else {
console.log('POST Failed');
}
}
})
console.log(JSON.stringify(data))
{"Peril":["BF","BF"],"OccurrenceYear":["2014","2016"],"Month":["1","1"],"Event":["",""],"InsuredLoss":["10020623.440000998","5370632.38"],"UnderWriterYear":["2013","2015"],"ReturnPeriod":[12,12],"SelectedIndex":["1.801998974252194","1.6036056232964842"],"TrendedLoss":["18057153.16024929","8612376.28522618"],"ReportingThreshold":""}
Model
public class HistoricalLossTable
{
public String[] Peril { get; set; }
public int[] OccurrenceYear { get; set; }
public int[] Month { get; set; }
public String [] Event { get; set; }
public double[] InsuredLoss { get; set; }
public int[] UnderWriterYear { get; set; }
public double[] ReturnPeriod { get; set; }
public double[] SelectedIndex { get; set; }
public double[] TrendedLoss { get; set; }
public double ReportingThreshold { get; set; }
}
And Controller
[HttpPost]
public IActionResult test([FromBody]HistoricalLossTable table)
{
return View();
}
As derloopkat said in comment, you should not make the number fields as string. Try to convert your payload like below:
{
"Peril":[
"BF",
"BF"
],
"OccurrenceYear":[
2014,
2016
],
"Month":[
1,
1
],
"Event":[
"",
""
],
"InsuredLoss":[
10020623.440000998,
5370632.38
],
"UnderWriterYear":[
2013,
2015
],
"ReturnPeriod":[
12,
12
],
"SelectedIndex":[
1.801998974252194,
1.6036056232964842
],
"TrendedLoss":[
18057153.16024929,
8612376.28522618
]
}
I will suggest trying type to string based on your json and add constructor to initialize array(weird but can be an issue). Try with :
public class HistoricalLossTable
{
public string[] Peril { get; set; }
public string[] OccurrenceYear { get; set; }
public string[] Month { get; set; }
public string[] Event { get; set; }
public string[] InsuredLoss { get; set; }
public string[] UnderWriterYear { get; set; }
public string[] ReturnPeriod { get; set; }
public string[] SelectedIndex { get; set; }
public string[] TrendedLoss { get; set; }
public string ReportingThreshold { get; set; }
public HistoricalLossTable()
{
Peril = new string[2];
OccurrenceYear = new string[2];
Month = new string[2];
Event = new string[2];
InsuredLoss = new string[2];
UnderWriterYear = new string[2];
ReturnPeriod = new string[2];
SelectedIndex = new string[2];
TrendedLoss = new string[2];
}
}

Some elements from JSON object passed to MVC controller are NULL

I am trying to pass a JSON object to my MVC controller action via POST. The controller action is called but some elements of the object are NULL. The 'ArticleKey' is there but the 'MeasureDefinitions' are NULL (see below).
Here is the object which I am trying to parse (it gets appended with more values by the user):
var articleValues = [
{
'ArticleKey': {
'ArticleNo': 'ArticleNo',
'CustomerName': 'CustomerName',
},
'MeasureDefinitions ': [
{
'DisplayIndex': 0,
'MeasureType': 'MeasureType',
'Percentage': 99.99,
'OriginalPercentage': 0
}
]
}
];
My model looks like this:
public class ArticleValuesModel
{
[Key]
public ArticleKey ArticleKey { get; set; }
public List<MeasureDefinition> MeasureDefinitions { get; set; }
public string ArticleDescription { get; set; }
public bool AddToList { get; set; }
}
public class ArticleKey
{
public string ArticleNo { get; set; }
public string CustomerName { get; set; }
}
public class MeasureDefinition
{
public long DisplayIndex { get; set; }
[Key]
public string MeasureType { get; set; }
public double Percentage { get; set; }
public double OriginalPercentage { get; set; }
}
Here is my controller action:
[HttpPost]
public ActionResult UpdateArticleValuesJson(List<Gui.Models.ArticleValuesModel> modelList)
{
return RedirectToAction("Index");
}
Here is my Ajax POST:
$('#btnSaveArticleValues').click(function() {
$.ajax({
url: "/ArticleList/UpdateArticleValuesJson",
contentType: "application/json;charset=utf-8",
dataType: "JSON",
type: "POST",
data: JSON.stringify(articleValues),
success: function() {
console.log("Saved");
},
error: function(e) {
console.log(e);
}
});
});
Can you please help me to make the 'MeasureDefinitions' list accessible in my controller?
Removing the extra spaces in my JSON object like indicated by the_lotus did help to resolve the problem.

Passing a list from angular to c# through http request

My method in c# receives a list as a parameter, I am trying to call this method in angular by passing it an array, but the problem is that the info doesn't reach the c# method, the list is always empty, even though there was information in the angular array.
export class StationAllocationPostModel{
idAppDeviceOwnerEntity: number;
idAppDeviceOwnerEntityOriginal: number;
idAppDeviceOwnerEntityRentalLocationId: number;
Observations: string;
selectedAppDevices: StationAllocationModel[];
}
createNewStationAllocation(selectedAppDevices: StationAllocationPostModel){
return this.post("home/CreateAppDeviceRentalLocationAllocation", selectedAppDevices, {
params: {
'idAppDeviceOwnerEntity': selectedAppDevices.idAppDeviceOwnerEntity,
'idAppDeviceOwnerEntityRentalLocationId': selectedAppDevices.idAppDeviceOwnerEntityRentalLocationId,
'Observations': selectedAppDevices.Observations,
'selectedAppDevices': selectedAppDevices.selectedAppDevices
}
});
}
public post(url: string, data: any, options = null) {
return new Promise<any>((resolve, reject) => {
let response;
this.http.post(
this.baseUrl + url,
{
data: data
},
{
headers: options ? options.headers : null,
observe: options ? options.observe : null,
params: options ? options.params : null,
reportProgress: options ? options.reportProgress : null,
responseType: options ? options.responseType : null,
withCredentials: options ? options.withCredentials : null
}
)
.subscribe(
data => {
response = data;
if (response && !response.success) {
if (response.response.ServerResponse[0].MessageType == "NOSESSIONEXCEPTION") {
localStorage.removeItem('userSession');
this.router.navigate(['/login'], { queryParams: { returnUrl: this.router.url } });
}
}
},
error => {
resolve(null);
this.handleError(url, options ? options.params : null );
console.log(error);
}, () => {
if (response) {
resolve(response);
} else {
resolve(null);
}
}
);
})
}
This is my c# method:
public Object CreateAppDeviceRentalLocationAllocation(<other params>, List<AppDeviceRentalLocationAllocationHistoryExtended> selectedAppDevices)
{
...
}
I am expecting that the c# method receives a list with elements, but it always comes out empty for some reason. The 'other params' are getting the right information, so I don't know what's wrong with the list.
Sorry for the long post, I'm new here.
Could you please form a param object on the C# method that holds the following :
public class SelectedAppDevice
{
public int idAppDevice { get; set; }
public int idAppDeviceOwnerEntity { get; set; }
public int idAppDeviceOwnerEntityRentalLocationId { get; set; }
public string Observations { get; set; }
public string DeviceId { get; set; }
public string EntityRentalLocationName { get; set; }
public DateTime CreationDate { get; set; }
public DateTime EndDate { get; set; }
public string CreatedByUserName { get; set; }
public int RentalStatus { get; set; }
public int idAppDeviceRental { get; set; }
public bool IsRentalStart { get; set; }
public bool IsRentalEnd { get; set; }
public object idNextExpectedEntityRentalLocationName { get; set; }
public object NextExpectedEntityRentalLocationName { get; set; }
public string LastKnownEntityRentingId { get; set; }
public string CallerId { get; set; }
public int RentalStatusId { get; set; }
public int DeviceStatusId { get; set; }
}
public class Data
{
public string Observations { get; set; }
public int idAppDeviceOwnerEntityRentalLocationId { get; set; }
public int idAppDeviceOwnerEntity { get; set; }
public List<SelectedAppDevice> selectedAppDevices { get; set; }
}
public class RootObject
{
public Data data { get; set; }
}
and make it as a controller method parameter :
public Object CreateAppDeviceRentalLocationAllocation(RootObject param)
{
...
}

KendoUI treeview children are displayed as undefined

I have a treeview in kendoUI in which main nodes are calling into an mvc controller and that controller looks to whether there is an nullable id passed in and then uses a different model.
What I hit the url : http://localhost:2949/Report/GetReportGroupAssignments
I see this JSON
[
{"Id":1,"ReportGroupName":"Standard Reports","ReportGroupNameResID":null,"SortOrder":1},
{"Id":2,"ReportGroupName":"Custom Reports","ReportGroupNameResID":null,"SortOrder":2},
{"Id":3,"ReportGroupName":"Retail Reports","ReportGroupNameResID":null,"SortOrder":3},
{"Id":4,"ReportGroupName":"Admin Reports","ReportGroupNameResID":null,"SortOrder":5},
{"Id":5,"ReportGroupName":"QA Reports","ReportGroupNameResID":null,"SortOrder":4}
]
Now my mvc controller looks like this
public JsonResult GetReportGroupAssignments(int? id)
{
var model = new List<ReportGroup>();
var defModel = new List<ReportDefinition>();
try
{
if (id == null)
{
model = _reportService.GetReportGroups("en-us").ToList();
return Json(model, JsonRequestBehavior.AllowGet);
}
else
{
defModel = _reportService.GetReportDefinitions().Where(e=>e.ReportGroupID ==Convert.ToInt32(id)).ToList();
return Json(defModel, JsonRequestBehavior.AllowGet);
}
}
catch (Exception ex)
{
Logger.Error(ex, "Error loading LoadReportList.");
return null;
}
}
My Kendo javascript looks like the following:
var serviceRoot = "/Report"; // "//demos.telerik.com/kendo-ui/service";
homogeneous = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: serviceRoot + "/GetReportGroupAssignments", //"/LoadReportTree", // "/Employees",
dataType: "json"
}
},
schema: {
model: {
id: "Id" //"ReportGroupName"
,hasChildren: "Id"
}
}
});
var treeview = $("#treeview").kendoTreeView({
expanded: true,
dragAndDrop: true,
dataSource: homogeneous,
dataTextField: "ReportGroupName"
}).data("kendoTreeView");
Seems that the calls (which I discovered that children records have a "load" method that it called behind the seens, so basically I pass in the ID in order to get the data from the other model ( table in db)
(Id is mapped with automapper to ReportGroupID )
So when i click to the left of "Standard Rports" I am getting all of these children as undefined, How do I get these to show up properly?
Update: My ReportDefinition class:
public class ReportDefinition {
public override int Id { get; set; }
public string ReportKey { get; set; }
public string ReportName { get; set; }
public int? ReportNameResID { get; set; }
public string ReportDef { get; set; }
public int? ReportDefinitionResID { get; set; }
public string ReportAssembly { get; set; }
public string ReportClass { get; set; }
public int ReportGroupID { get; set; }
public int AppID { get; set; }
public int SortOrder { get; set; }
public bool IsSubReport { get; set; }
}
I think your problem is that the class ReportDefinition does not have a property called: ReportGroupName. That is why TreeView displays 'undefined'.
Try adding this Property to your ReportDefinition class like:
public class ReportDefinition {
// Other Properties
// I guess this property is missing
public string ReportGroupName { get; set; }
}

Breeze.js /NET+EF complex object behaviors rather strange

I’m developing a custom data access layer to be consumed in breeze.js
What I have:
The Model:
public class Product
{
[Key]
public int ProductId { get; set; }
public string Upc { get; set; }
public string Name { get; set; }
public decimal MsrpPrice { get; set; }
public int Quantity { get; set; }
public virtual ICollection<ProductFeature> Features { get; set; }
public virtual B2BCategory InB2BCategory { get; set; }
public virtual ICollection<ImageDescriptor> Images { get; set; }
public int CategoryId {get; set;}
}
public class ProductFeature
{
public int ProductId { get; set; }
public string Name { get; set; }
public string GroupName { get; set; }
public string Operation { get; set; }
public decimal Value { get; set; }
}
public class ImageDescriptor
{
public int ProductId { get; set; }
public string Uri { get; set; }
public DateTime Updated { get; set; }
public bool IsDefault { get; set; }
}
The Context Provider:
public class ProductContextProvider : ContextProvider
{
private readonly ProductRepository repo =new ProductRepository();
public IQueryable<B2BCategory> Categories
{
get { return repo.Categories.AsQueryable(); }
}
public IQueryable<Product> Products
{
get
{
return repo.Products.OrderBy(p => p.ProductId).AsQueryable();
}
}
protected override string BuildJsonMetadata()
{
var contextProvider = new EFContextProvider<ProductMetadataContext>();
return contextProvider.Metadata();
}
protected override void SaveChangesCore(SaveWorkState saveWorkState)
{…
}
// No DbConnections needed
public override IDbConnection GetDbConnection()
{
return null;
}
protected override void OpenDbConnection()
{
// do nothing
}
protected override void CloseDbConnection()
{
// do nothing
}
}
internal class ProductMetadataContext : DbContext
{
static ProductMetadataContext()
{
Database.SetInitializer<ProductMetadataContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ProductFeatureConfiguration());
modelBuilder.Configurations.Add(new ImageDescriptorConfiguration());
}
public DbSet<Product> Products { get; set; }
public DbSet<B2BCategory> Categories { get; set; }
}
internal class ImageDescriptorConfiguration : EntityTypeConfiguration<ImageDescriptor>
{
public ImageDescriptorConfiguration()
{
// I tried to mess up with key orders
HasKey(i => new { i.Uri, i.ProductId});
}
}
internal class ProductFeatureConfiguration : EntityTypeConfiguration<ProductFeature>
{
public ProductFeatureConfiguration()
{
HasKey(f => new { f.ProductId, f.Name });
}
}
I’m stuffing the Features and Images properties of a Product directly:
product.Features = new Collection<ProductFeature>();
product.Images = new Collection<ImageDescriptor>();
…
var imgd = new ImageDescriptor
{
ProductId = product.ProductId,
Updated = DateTime.Now,
Uri = defsmall,
IsDefault = !product.Images.Any()
}
product.Images.Add(imgd);
…
var pf = new ProductFeature
{
ProductId = product.ProductId,
GroupName = "Size",
Name = size,
Value = size == "Small" ? new decimal(.75):size == "Medium" ? new decimal(1.3):new decimal(1.8),
Operation = "*"
};
product.Features.Add(pf);
Totally there are, say, 3 product features and 2 images per product item.
In the client side I query this like:
return entityQuery.from('Products').using(EntityManager).execute();
And… I’ve got the very strange thing:
The images property contains an empty array, the features property contains an array of 5!!! elements – 3 of type ProductFeature and 2 of type ImageDescriptor.
I think this is a bug – could you help me, please?
I don't see any code that creates a breeze EntityManager and adds or attaches your newly created entities and then saves them. Please take a look at the Breeze examples in the downloadable zip from the BreezeJs website.

Categories

Resources