Fletch
Fletch

Reputation: 367

How to pass List model to controller from view http post

I have a CategoryModel that contains a list item for the ItemModel as well as some other strings etc.

I'm trying to pass the list from the view to the controller. The model on the view is the ABCModel which contains a list of 'Categories' of type CategoryModel. On the view I'm only looking to post the 'active' Category back to be saved.

When I do this the active category is passed with details added from the form but the list of items is null.

.cs Models

    namespace Company.Models
    {
        public class ABCModel
        {
            public IList<CategoryModel> Categories;
            public SummaryModel Summary;
        }
    }
    
    namespace Company.Models
    {
    public class CategoryModel
    {
        public string Label { get; set; }
        public bool Active { get; set; }
        public decimal Amount { get; set; }
        public string Frequency { get; set; }
        public string Type { get; set; }
        public List<ItemModel> Items;
    }
    )
    
    namespace Company.Models
    {
    public class ItemModel
    {
        public string Label { get; set; }
        public string Explanation { get; set; }
        public string Amount { get; set; }
        public string Frequency { get; set; }
        public bool Flag { get; set; }
        public string Note { get; set; }
    }
    }

Controller

    [HttpPost]
        public ActionResult SaveItems([FromForm] CategoryModel activeCategoryModel, [FromForm] List<ItemModel> items, [FromQuery] string activecategory, [FromQuery] string nextcategory)
        {
        ...
        }

View

    @model ABCModel

    @{ CategoryModel nextCategory = null; }
    @{ CategoryModel activeCategoryModel = null; }
    
    @if (Model.Categories.Any())
    {
        @for (var i = 0; i < Model.Categories.Count; i++)
        {
            Company.Models.CategoryModel category = Model.Categories[i];
    
            @if (category.Active)
            {
                activeCategoryModel = category;
                if ((i + 1 < Model.Categories.Count) && (Model.Categories[i + 1] != null))
                {
                    nextCategory = Model.Categories[i + 1];
                }
            }
        }
    }
    
    <form id="ABC-form" class="needs-validation" novalidate="" asp-action="SaveItems" asp-controller="Home" method="post">
    
            @if (activeCategoryModel != null)
            {
                <input asp-for="@activeCategoryModel.Label" type="hidden" />
                <input asp-for="@activeCategoryModel.Active" type="hidden" />
                <input asp-for="@activeCategoryModel.Amount" type="hidden" />
                <input asp-for="@activeCategoryModel.Frequency" type="hidden" />
                <input asp-for="@activeCategoryModel.Type" type="hidden" />

                @if (activeCategoryModel.Items.Any())
                {    
                    @for (var i = 0; i < activeCategoryModel.Items.Count; i++)
                    {
                        @Html.HiddenFor(x => activeCategoryModel.Items[i].Label)
                        @Html.HiddenFor(x => activeCategoryModel.Items[i].Explanation)
                        @Html.TextBoxFor(x => items[i].Amount, new { @class = "form-control" })
                    }
                }
            }
        <button id="continue" type="submit" asp-action="SaveItems" asp-route-activecategory="@activeCategoryModel.Label" asp-route-nextcategory="@(nextCategory != null ? nextCategory?.Label : null)">Continue</button>
    </form>

I had been including IFormCollection as a parameter within the SaveItems on the controller and this showed that the items are being passed in the format I was thinking would work but the model only shows the values entered and the list of items is null.

IFormCollection on hover in debug on controller

activeCategoryModel on hover in debug on controller - items = null

How can I populate the list of items on the active category model from the view?

Upvotes: 0

Views: 2844

Answers (1)

Rena
Rena

Reputation: 36715

Items in CategoryModel should be a property not a filed,so your CategoryModel should be like below:

public class CategoryModel
{
    public string Label { get; set; }
    public bool Active { get; set; }
    public decimal Amount { get; set; }
    public string Frequency { get; set; }
    public string Type { get; set; }
    public List<ItemModel> Items { get; set; }
}

Upvotes: 1

Related Questions