4

I am working on a project which requires POST method for a multiple-array Json where the data are located on 5 different relating tables with FK.

here is the Json output using GET:

{
 "UserId": 1,
 "Id": 1,
 "ValueStoryName": "Value Story 101",
 "Organization": "Charity Foundation",
 "Industry": "Education",
 "Location": "Singapore",
 "AnnualRevenue": 1000,
 "CreatedDate": "2017-07-27T00:00:00",
 "ModifiedDate": "2017-01-01T00:00:00",
 "BusinessValueToYou": [
 {
 "Id": 1,
 "BVUSId": 1,
 "BalanceSheet": 348,
 "IncomeStatement": 546,
 "ValueDriver": [
 {
 "BVUSId": 1,
 "BVUId": 1,
 "ValueDriver": "Give kind to others",
 "Selected": true,
 "TotalSavings": 0,
 "SubLever": [
 {
 "BVUId": 1,
 "BVUSVDId": 1,
 "Item": "Help when needed",
 "Selected": true,
 "EstAnnualValue": 1,
 "UserInput": [
 {
 "BVUSVDId": 1,
 "BVUUIId": 1,
 "Item": "Total Benefit",
 "UserInput": 10
 }
 ]
 }
 ]
 }
 ]
 }
 ]
}

and what I currently have for my POST method under the controller is:

// POST: api/ValueStories
[ResponseType(typeof(ValueStory))]
public async Task<IHttpActionResult> PostValueStory(ValueStory valueStory)
{
 if (!ModelState.IsValid)
 {
 return BadRequest(ModelState);
 }
 db.ValueStories.Add(valueStory);
 db.BusinessValueToYou.AddRange(valueStory.BusinessValueToYou);
 await db.SaveChangesAsync();
 return CreatedAtRoute("DefaultApi", new { id = valueStory.Id }, valueStory);
}

the code above only adds data for valuestory and businessvaluetoyou but is unable to add values for the valuedriver, subvaluedriver and userinput. I've been cracking by brain on how to make this work but to no luck. Any help and references will be very much appreciated.

This is my BusinessValueToYou model:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace AribaWebService.Models
{
 public class BusinessValueToYou
 {
 // Foreign Key
 public int Id { get; set; }
 [Key]
 public int BVUSId { get; set; }
 public decimal BalanceSheet { get; set; }
 public decimal IncomeStatement { get; set; }
 // Navigation property
 public virtual ValueStory ValueStory { get; set; }
 public List<BVUValueDriver> ValueDriver { get; set; }
 }
 public class BVUValueDriver
 {
 // Foreign Key
 public int BVUSId { get; set; }
 [Key]
 public int BVUId { get; set; }
 [Required]
 public string ValueDriver { get; set; }
 public bool Selected { get; set; }
 public decimal TotalSavings { get; set;}
 // Navigation property
 public virtual BusinessValueToYou BusinessValueToYou { get; set; } 
 public List<BVUSubValueDriver> SubLever { get; set; }
 }
 public class BVUSubValueDriver
 {
 // Foreign Key
 public int BVUId { get; set; }
 [Key]
 public int BVUSVDId { get; set; }
 [Required]
 public string Item { get; set; }
 public bool Selected { get; set; }
 public decimal EstAnnualValue { get; set; }
 // Navigation property
 public virtual BVUValueDriver BVUValueDriver { get; set; }
 public List<BVUUserInput> UserInput { get; set; }
 }
 public class BVUUserInput
 {
 // Foreign Key
 public int BVUSVDId { get; set; }
 [Key]
 public int BVUUIId { get; set; }
 [Required]
 public string Item { get; set; }
 public double UserInput { get; set; }
 // Navigation property
 public virtual BVUSubValueDriver BVUSubValueDriver { get; set; }
 }
}

here is my ValueStory model:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace AribaWebService.Models
{
 public class ValueStoryDetailDTO
 {
 // Foreign Key
 public int UserId { get; set; } 
 [Key]
 public int Id { get; set; }
 public string ValueStoryName { get; set; }
 public string Organization { get; set; }
 public string Industry { get; set; }
 public string Location { get; set; }
 public string Currency { get; set; }
 public double AnnualRevenue { get; set; }
 public DateTime CreatedDate { get; set; }
 public DateTime ModifiedDate { get; set; }
 // Navigation property
 [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
 public virtual User User { get; set; }
 public List<AreaOfInterest> AreaOfInterest { get; set; }
 public List<BusinessValueToYou> BusinessValueToYou { get; set; }
 public List<BusinessValueFromSap> BusinessValueFromSap { get; set; }
 }
}
asked Aug 10, 2017 at 3:23
6
  • What do you mean by "is unable to add values.."? Are ValueStory and BusinessValueToYou populated but ValueDriver and SubValueDriver are null? Commented Aug 10, 2017 at 3:31
  • Are you using Entity Framework? Could you add in the code for your model? Commented Aug 10, 2017 at 3:44
  • @arkane, I've updated my post. When executing the POST method, its only inserting data to ValueStory and BusinessValueToYou. The ValueDriver, SubValueDriver and UserInput doesnt gets updated. Commented Aug 10, 2017 at 3:50
  • @Poosh, yes, I am using EF Commented Aug 10, 2017 at 3:50
  • @RaymundEvangelista can you add your ValueStory model into your question also? Did you try to use db.BusinessValueToYou.AddRange(valueStory.BusinessValueToYou.BVUValueDriver); Commented Aug 10, 2017 at 11:46

2 Answers 2

2

Usually we don't expose the real Db entities directly in web api, just return what we need using view model or DTO to prevent overexpose.

You can change your get method to return what you need in a single model.

Learn more about auto mapper http://automapper.org/

Build better RESTful api: https://www.codeproject.com/Articles/990492/RESTful-Day-sharp-Enterprise-Level-Application

For your question this is a example how to read multiple array:

// POST: api/ValueStories
public async Task<IHttpActionResult> PostValueStory(AbcViewModel viewModel)
{
 if (!ModelState.IsValid)
 {
 return BadRequest(ModelState);
 }
 //Manual map or use Automapper here
 var entity = Mapper.Map<ValueStory>(viewModel);
 db.ValueStories.Add(entity);
 //db.BusinessValueToYou.AddRange(entity.BusinessValueToYou); // can map with automapper
 await db.SaveChangesAsync();
 return CreatedAtRoute("DefaultApi", new { id = entity .Id }, entity );
}
public class AbcViewModel
{
 public int UserId { get; set; }
 public int Id { get; set; }
 public string ValueStoryName { get; set; }
 public string Organization { get; set; }
 public string Industry { get; set; }
 public string Location { get; set; }
 public string AnnualRevenue { get; set; }
 public DateTime CreatedDate { get; set; }
 public DateTime ModifiedDate { get; set; }
 public IEnumerable<BusinessValueToYouViewModel> BusinessValueToYou { get; set; }
}
public class BusinessValueToYouViewModel
{
 public int Id { get; set; }
 public int BVUSId { get; set; }
 public int BalanceSheet { get; set; }
 public int IncomeStatement { get; set; }
 public IEnumerable<ValueDriverViewModel> ValueDriver { get; set; }
}
public class ValueDriverViewModel
{
 public int Id { get; set; }
 public int BVUSId { get; set; }
 public int BVUId { get; set; }
 public string ValueDriver { get; set; }
 public bool Selected { get; set; }
 public int TotalSavings { get; set; }
}
answered Aug 11, 2017 at 3:29

2 Comments

thanks for introducing me to Automapper. I tried your code above but I am getting this error on line 425 which is referring to the mapper: [link]ibb.co/hbYvZv
You have to go through Automapper document github.com/AutoMapper/AutoMapper/wiki/Getting-started. You get this error because you did not init config for automapper. Put something like this in application entry point Mapper.Initialize(cfg => cfg.AddProfile<AutoMapperProfile>());
0

I managed to get it working using AddRange. Thanks for the help.

answered Aug 14, 2017 at 7:58

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.