简体   繁体   中英

C# Web API POST method for Json Multiple Array

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; }


    }
}

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; }
}

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM