0

Is there a way to find the values from a form submitted during a HTTP Post request, even though they're not declared on the view model or as parameters on the action method? Of course on ASP.NET CORE MVC.

I'll give you more context of what i'm trying to do.

I'm trying to insert a product into the database.Take look at it's class and dependencies then product view model and finally it's view.
Brief summary:

  • Each Product has many subcategories

  • Each Subcategory has many products

  • Therefore the ProductSubcategory class.

  • Each Product has a category.


Product.cs

public class Product
    {
        public int ProductId { get; set; }
        public string Name { get; set; }
        public double Price { get; set; }
        public Category Category { get; set; }
        public IEnumerable<ProductSubCategory> SubCategories { get; set; } 
}

ProductSubCategory.cs

public class ProductSubCategory
{
    public int ProductId { get; set; }
    public Product Product { get; set; }
    public int SubCategoryId { get; set; }
    public SubCategory SubCategory { get; set; }
}

SubCategory.cs

public class SubCategory
{
    public int SubCategoryId { get; set; }
    public string Name { get; set; }
    public Category Category { get; set; }
    public IEnumerable<ProductSubCategory> ProductSubCategories { get; set; }
}

Category.cs

public class Category
{
    public int CategoryId { get; set; }
    public string Name { get; set; }
    public IEnumerable<Product> Products { get; set; }
}


ProductViewModel.cs

public class ProductViewModel
{
    public int ProductId { get; set; }
    public string Name { get; set; }
    public double? Price { get; set; }
    public SelectList Categories { get; set; }
    public int? CategoryId { get; set; }
}


Insert.cshtml

  • In order to get a or many SubCategories, you have to pick a category from the select first.
@model ProductViewModel
<form enctype="multipart/form-data" method="post" asp-controller="Product" asp-action="Add">
            <div class="form-group">
                <label asp-for="Name"></label>
                <input type="text" class="form-control" asp-for="Name" placeholder="Cereal, Ice cream, Tuna, etc...">
            </div>
            <div class="form-group">
                <label asp-for="Price"></label>
                <input type="text" class="form-control" asp-for="Price" placeholder="5 , 23.5 , 50.231">
            </div>
            <div class="form-group">
                <label asp-for="Categories"></label>
                <select asp-for="CategoryId" asp-items="@Model.Categories" class="custom-select">
                    <option value="">Please select one</option>
                </select>
            </div>
            <label>Subcategories</label>
            @* Here we'll put the subcategories ( <input type="checkbox"/> ) according to the category selected,
             each subcategory will be represented by a checkbox *@
            <button class="btn btn-primary">Create</button>
        </form>

Okay now comes the problem I don't know how to map/find/search the subcategories (<input type="checkbox"/>) marked by the user on the view, since they're not declared directly on the view and view model. Why? Because it's impossible, since the amount of subcategories will rely on the category selected by the user, so if he pick the candy category, then subcategories as caramel,chocolate and gummies will show below, and if he pick the meat category, then subcategories as pork,chicken and beef will show below and so on... each one represented by a <input type="checkbox"/>.
I have to know which were selected because then on the controller i have to make some sort of algorithm in order to create a subcategory instance(s) and assign them to the product instance so then i can finally insert it.

Manguera v
  • 412
  • 2
  • 6
  • 15
  • 1
    Sounds like you want a dynamic form that changes as the user selects options. You can do this with JavaScript and multiple AJAX calls to fetch the sub-options (see here for an example https://stackoverflow.com/questions/18351921/how-to-populate-a-cascading-dropdown-with-jquery). The final submission will need all the relevant input elements or you can build a json object which you will POST. – Jasen Oct 27 '20 at 22:04
  • @Jasen Yes, it is a dynamic form, i have an idea of how to make it dynamic.That's not what I'm asking for . How does the Controller - Post Action Method know which subcategories were selected? Because it can be 4 or 5 or 6 , who knows. I need to be sure, otherwise i can't create the subcategory's, and then insert the ProductSubCategory. – Manguera v Oct 28 '20 at 00:10

1 Answers1

1

I made a demo based on your codes and description, you can refer to the below codes:

ViewModel:

public class ProductViewModel
{
    public int ProductId { get; set; }
    public string Name { get; set; }
    public double? Price { get; set; }
    public List<SelectListItem> Categories { get; set; }
    public int? CategoryId { get; set; }
}

View:

@model ProductViewModel

<form enctype="multipart/form-data" method="post" asp-controller="Product" asp-action="Create">
    <div class="form-group">
        <label asp-for="Name"></label>
        <input type="text" class="form-control" asp-for="Name" placeholder="Cereal, Ice cream, Tuna, etc...">
    </div>
    <div class="form-group">
        <label asp-for="Price"></label>
        <input type="text" class="form-control" asp-for="Price" placeholder="5 , 23.5 , 50.231">
    </div>
    <div class="form-group">
        <label asp-for="Categories"></label>
        <select asp-for="CategoryId" asp-items="@Model.Categories" class="custom-select">
            <option value="">Please select one</option>
        </select>
    </div>
    <label>Subcategories</label>
    <div id="subcategories"></div>
    <button class="btn btn-primary">Create</button>

</form>

@section scripts{ 
<script>
    $("#CategoryId").on("change", function () {
        var categoryId = $(this).val();
        $.ajax({
            method: 'get',
            url: '/Product/GetSubCategories?categoryId=' + categoryId,
            success: function (result) {
                var htmlString = "";
                for (var i = 0; i < result.length; i++) {
                    htmlString += "<input type='checkbox' name='subCategories' value = '" + result[i].subCategoryId + "' />";
                    htmlString += "<label>"+result[i].name+"</label>"
                }
                $("#subcategories").append(htmlString);
            }

        })

    })
</script>
}

Controller:

public IActionResult Create()
{
    var categories = _db.Categories.ToList();
    var viewModel = new ProductViewModel();
    var categorylist = new List<SelectListItem>();
    foreach (var category in categories)
    {

        categorylist.Add(
            new SelectListItem()
            {
                Text = category.Name,
                Value = category.CategoryId.ToString()
            });
    }
    viewModel.Categories = categorylist;
    return View(viewModel);
}

public List<SubCategory> GetSubCategories(int categoryId)
{
    var subcategories = _db.SubCategories.Where(s => s.Category.CategoryId == categoryId).ToList();
    return subcategories;
}

[HttpPost]
public IActionResult Create(Product product, List<int> subCategories)
{
    //do stuff     
    return View();
}

Result:

enter image description here

mj1313
  • 7,930
  • 2
  • 12
  • 32
  • Dude, you're the best, you just give more than i asked for, thanks to that i eliminate all my doubts. – Manguera v Oct 28 '20 at 15:37
  • does asp.net core mvc have some sort of tag helper to make AJAX easier? It's because i have to learn AJAX, so if there's a way to make my code much cleanier, it would be great. – Manguera v Oct 28 '20 at 15:39
  • what if I have thousands subcategories or more than that. we can't do that much checkboxes. – Sudhananda Biswas Aug 18 '21 at 22:14