Reputation: 428
My problem is: I am unable to pass array data from the view (HTML-select component multiple in mode) to the controller where there is a one-to-many relationship.
I tried to use Microsoft.AspNetCore.Mvc.TagHelpers
for the view.
Please see the MVC design (I simplified it):
Model
public class Product
{
[Key]
public int id { get; set; }
public string? Name { get; set; }
[ForeignKey("ProductCategory")]
public int Categoryid { get; set; }
public ProductCategory ProductCategory{ get; set; }
}
public class ProductCategory
{
[Key]
public int id { get; set; }
public string Name { get; set; }
public IList<Product> Products{ get; set; }
}
View
@using Microsoft.EntityFrameworkCore
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model ProjectCategory
<form method="post">
<div class="container-fluid">
<div class="row">
<div class="col-12 col-lg-6 pt-3">
<label asp-for="Name"></label>
<input asp-for="Name" class="form-control"/>
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="col-12 col-lg-6 pt-3">
<label asp-for="Products"></label><br/>
<select id="Products" asp-for="Accounts" class="form-control" multiple>
<option value="">Please select products...</option>
@{
Context c = new Context();
var products = c.Products.ToList();
}
@foreach(var r in products){<option value="@r.id">@r.Name</option>}
</select>
<span asp-validation-for="Products" class="text-danger"></span>
</div>
<div class="col-12" >
<br/> <button type="submit"> Create</button>
</div>
</div>
</div>
</form>
<script>
// some js code to handle multiple select.. (selectize.js used)
</script>
Controller
public IActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(ProductCategory productcategory)
{
if (!ModelState.IsValid)
return View(productcategory);
// Problem is right here.
// in debug mode I see, productcategory.Products Count : 0
// I could not pass Products from the view to controller
Context c = new Context();
c.ProductCategories.Add(productcategory);
c.SaveChanges();
return RedirectToAction("Index");
}
I searched, I saw examples for passing multiple select items to controller but those examples are just with an array, there was no model like this one-to-many, passing model object like my example.
How to do that?
Upvotes: 2
Views: 5890
Reputation: 11
If you just want to have a List<int>
you can use a simpler way:
1- give a name property to select like:
<select name="BayiIdListesi" multiple>
2- after that you should rearrange your action like:
public IActionResult BayiTopluEmailGonder(List<int> BayiIdListesi)
or better:
public async Task<IActionResult> BayiTopluEmailGonder(List<int> BayiIdListesi)
Note: The tricky part is using same value (BayiIdListesi) for both select's name property and actions parameters name.
Upvotes: 0
Reputation: 6150
In your select, the option field value is id
, hence you should expect a list of Product.id
.
Follow the steps below;
public class ProductCategoryCreateViewModel {
public string Name {get;set;}
public List<int> ProductIds {get;set;}
}
[HttpPost]
[ValidateAntiForgeryToken]
// bind the form data to the view model
public IActionResult Create(ProductCategoryCreateViewModel viewModel)
{
if (!ModelState.IsValid)
return RedirectToAction("Create");
Context c = new Context();
// make a new ProductCategory using the ViewModel
ProductCategory newCategory = new ProductCategory();
// assign name to new category
newCategory.Name = viewModel.Name;
// save the category first so it will generate a new category id
c.ProductCategories.Add(newCategory);
c.SaveChanges();
// loop through all product ids selected, and update them with the newcategoryid
foreach(var id in viewModel.ProductIds){
// load the product
var updateProduct = c.Products.FirstOrDefault(p=>p.id == id);
if(updateProduct != null){
// if product is found, update the category id
updateProduct.Categoryid = newCategory.id;
c.SaveChanges();
}
}
return RedirectToAction("Index");
}
name="ProductIds"
to select tag. Remove for
attribute.<select name="ProductIds" id="Products" class="form-control" multiple>
...
</select>
Upvotes: 1