Reputation: 492
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
@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.
Upvotes: 0
Views: 787
Reputation: 8479
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:
Upvotes: 1