Hello,
In my project the company has a set of Stores where it operates. Each Store is located in a District and every District belongs to a Department (or city).
I'm trying to construct a view where I can show the Store properties (in a table) and I'm trying to add a cascading dropdownlist for the Departments and the Districts.
Here are the models so you can see the relationship between them:
Stores:
- public class Store
- {
- [Key]
- public int StoreID { get; set; }
- [Display(Name = "Distrito")]
- public int DistrictID { get; set; }
- [Display(Name = "Cadena")]
- public int StoreChainID { get; set; }
- [Required]
- [StringLength(60)]
- [Display(Name = "Nombre")]
- public string StoreName { get; set; }
- [StringLength(60)]
- [Display(Name = "Dirección")]
- public string StoreAddress { get; set; }
- [Display(Name = "Área")]
- public int StoreArea { get; set; }
-
- public virtual ICollection<Machine> Machines { get; set; }
- public virtual District Districts { get; set; }
- public virtual StoreChain StoreChains { get; set; }
- public virtual LocalExpenses LocalExpenses { get; set; }
District:
- public class District
- {
- [Key]
- public int DistrictID { get; set; }
- public int DepartmentID { get; set; }
- [StringLength(30)]
- public string DistrictName { get; set; }
-
- public virtual ICollection<Store> Stores{ get; set; }
- public virtual Department Departments { get; set; }
Department:
- public class Department
- {
- [Key]
- public int DepartmentID { get; set; }
- [StringLength(30)]
- public string DepartmentName { get; set; }
- [NotMapped]
- public int DistrictID {get;set;}
-
- public virtual ICollection<District> Districts { get; set; }
- }
In my Controller I have two actions for my Index. The first action populates the Index view (which has a table to show the stores) and gets the data for the list of Departments:
First action:
- public async Task<IActionResult> Index()
- {
- var plataformaContext = _context.Stores.Include(s => s.Districts).Include(c => c.StoreChains);
-
- List<Department> departmentlist = new List<Department>();
-
- departmentlist = (from department in _context.Departments select department).ToList();
-
- departmentlist.Insert(0, new Department { DepartmentID = 0, DepartmentName = "Select" });
- ViewBag.ListofDepartment = departmentlist;
- return View(await plataformaContext.ToListAsync());
- }
The second action is used to populate the dropdownlist:
- [HttpPost]
- public IActionResult Index(Department objdepartment, IFormCollection formCollection)
- {
-
- if (objdepartment.DepartmentID == 0)
- {
- ModelState.AddModelError("", "Select Department");
- }
- else if (objdepartment.DistrictID == 0)
- {
- ModelState.AddModelError("", "Select District");
- }
-
- var DistrictID = HttpContext.Request.Form["DistrictID"].ToString();
-
- List<Department> departmentList = new List<Department>();
- departmentList = (from department in _context.Departments
- select department).ToList();
- departmentList.Insert(0, new Department { DepartmentID = 0, DepartmentName = "Select" });
-
- ViewBag.ListofDepartment = departmentList;
-
- return View(objdepartment);
- }
Finally, here is the Index view:
- @model List<Application.Models.Store>
-
- @{
- ViewData["Title"] = "Index";
- }
-
- <h2>Index</h2>
-
- <p>
- <a asp-action="Create">Create New</a>
- </p>
- <table class="table">
- <thead>
- <tr>
- <th>
- Nombre de Tienda @*@Html.DisplayNameFor(model => model.Stores.StoreName)*@
- </th>
- <th>
- Address @*@Html.DisplayNameFor(model => model.Stores.StoreAddress)*@
- </th>
- <th>
- Area @*@Html.DisplayNameFor(model => model.Stores.StoreArea)*@
- </th>
- <th>
- Distrito @*@Html.DisplayNameFor(model => model.Stores.Districts)*@
- </th>
- <th>
- Cadena @*@Html.DisplayNameFor(model => model.Stores.StoreChains)*@
- </th>
- <th></th>
- </tr>
- </thead>
- <tbody>
- @foreach (var item in Model) {
- <tr>
- <td>
- @Html.DisplayFor(modelItem => item.StoreName)
- </td>
- <td>
- @Html.DisplayFor(modelItem => item.StoreAddress)
- </td>
- <td>
- @Html.DisplayFor(modelItem => item.StoreArea)
- </td>
- <td>
- @Html.DisplayFor(modelItem => item.Districts.DistrictID)
- </td>
- <td>
- @Html.DisplayFor(modelItem => item.StoreChains.StoreChainID)
- </td>
- <td>
- <a asp-action="Edit" asp-route-id="@item.StoreID">Edit</a> |
- <a asp-action="Details" asp-route-id="@item.StoreID">Details</a> |
- <a asp-action="Delete" asp-route-id="@item.StoreID">Delete</a>
- </td>
- </tr>
- }
- </tbody>
- </table>
-
- <form asp-controller="StoresGlobal" asp-action="Index" method="post" class="form-horizontal" role="form">
- <div class="form-group">
- <div class="row">
- <div class="alert-danger" aspp-validation-summary="ModelOnly"></div>
- <div class="col-xs-12 col-sm-6 col-md-6 col-lg-4">
- <label asp-for="DepartmentName" class="control-label"></label>
- <select asp-for="DepartmentID"
- class="form-control"
- asp-items="@(new SelectList(ViewBag.ListofDepartment,"DepartmentID","DepartmentName"))"></select>
- </div>
- </div>
- </div>
- </form>
Ok, so, yes, this is not working because I'm using a Store model in the Index:
- @model List<Application.Models.Store>
and at the same time I'm trying to insert a dropdownlist for the Department class which has no direct relation to the Store class. What alternative I have? I was thinking of using a ViewModel which would have both classes, like this:
- public class StoreLocationViewModel
- {
- public Store Stores { get; set; }
- public Department Departments { get; set; }
- }
With this, I would have to change my Index model like this:
- @model List<Application.Models.StoreLocationViewModel>
but I get this error:
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Collections.Generic.List`1[Application.Models.Store]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.List`1[Application.Models.StoreLocationViewModel]'.
The error is now in the Controller, since I'm sending this:
- var plataformaContext = _context.Stores.Include(c => c.StoreChains).Include(s => s.Districts)
- .ThenInclude(d=>d.Departments);
and no a StoreLocationViewModel, BUT, I can't send a StoreLocationViewModel because then I would require to add the StoreLocationViewModel to the Database, define a Key and I believe that is wrong, right?
I'm very experienced on this, so I thank you for the time to read this. Any help is welcome as always!
Thanks,
Regards.