Cascading Dropdownlist - Registering new Store

Jun 22 2017 8:36 PM
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:
  1.   public class Store  
  2.   {  
  3. [Key]  
  4. public int StoreID { getset; }  
  5. [Display(Name = "Distrito")]  
  6. public int DistrictID { getset; }  
  7. [Display(Name = "Cadena")]  
  8. public int StoreChainID { getset; }  
  9. [Required]  
  10. [StringLength(60)]  
  11. [Display(Name = "Nombre")]  
  12. public string StoreName { getset; }  
  13. [StringLength(60)]  
  14. [Display(Name = "Dirección")]  
  15. public string StoreAddress { getset; }  
  16. [Display(Name = "Área")]  
  17. public int StoreArea { getset; }  
  18.   
  19. public virtual ICollection<Machine> Machines { getset; }  
  20. public virtual District Districts { getset; }  
  21. public virtual StoreChain StoreChains { getset; }  
  22. public virtual LocalExpenses LocalExpenses { getset; }  
District: 
  1.   public class District  
  2.   {  
  3. [Key]  
  4. public int DistrictID { getset; }  
  5. public int DepartmentID { getset; }  
  6. [StringLength(30)]  
  7. public string DistrictName { getset; }  
  8.   
  9. public virtual ICollection<Store> Stores{ getset; }  
  10. public virtual Department Departments { getset; }  
Department: 
  1.     public class Department  
  2.     {  
  3.         [Key]  
  4.         public int DepartmentID { getset; }  
  5.         [StringLength(30)]  
  6.         public string DepartmentName { getset; }  
  7.         [NotMapped]  
  8.         public int DistrictID {get;set;}  
  9.           
  10. public virtual ICollection<District> Districts { getset; }  
  11.     }  
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:
 
  1. public async Task<IActionResult> Index()  
  2.         {  
  3.             var plataformaContext = _context.Stores.Include(s => s.Districts).Include(c => c.StoreChains);  
  4.   
  5.             List<Department> departmentlist = new List<Department>();  
  6.             //Getting the Data from DB  
  7.             departmentlist = (from department in _context.Departments select department).ToList();  
  8.             //Inserting an additional item into the list: The "Select"  
  9.             departmentlist.Insert(0, new Department { DepartmentID = 0, DepartmentName = "Select" });  
  10.             ViewBag.ListofDepartment = departmentlist;  
  11.             return View(await plataformaContext.ToListAsync());  
  12.         }  
 The second action is used to populate the dropdownlist:
 
  1. [HttpPost]  
  2.         public IActionResult Index(Department objdepartment, IFormCollection formCollection)  
  3.         {  
  4.             //Validación  
  5.             if (objdepartment.DepartmentID == 0)  
  6.             {  
  7.                 ModelState.AddModelError("""Select Department");  
  8.             }  
  9.             else if (objdepartment.DistrictID == 0)  
  10.             {  
  11.                 ModelState.AddModelError("""Select District");  
  12.             }  
  13.             //Getting the selected value  
  14.             var DistrictID = HttpContext.Request.Form["DistrictID"].ToString();  
  15.             //Sending the data back to ViewBag after Posting Form  
  16.             List<Department> departmentList = new List<Department>();  
  17.             departmentList = (from department in _context.Departments  
  18.                               select department).ToList();  
  19.             departmentList.Insert(0, new Department { DepartmentID = 0, DepartmentName = "Select" });  
  20.             // Assigning departmentList to ViewBag  
  21.             ViewBag.ListofDepartment = departmentList;  
  22.               
  23.             return View(objdepartment);  
  24.         }  
Finally, here is the Index view:
 
 
  1. @model List<Application.Models.Store>  
  2.   
  3. @{  
  4.     ViewData["Title"] = "Index";  
  5. }  
  6.   
  7. <h2>Index</h2>  
  8.   
  9. <p>  
  10.     <a asp-action="Create">Create New</a>  
  11. </p>  
  12. <table class="table">  
  13.     <thead>  
  14.         <tr>  
  15.                 <th>  
  16.                     Nombre de Tienda @*@Html.DisplayNameFor(model => model.Stores.StoreName)*@  
  17.                 </th>  
  18.                 <th>  
  19.                     Address @*@Html.DisplayNameFor(model => model.Stores.StoreAddress)*@  
  20.                 </th>  
  21.                 <th>  
  22.                     Area @*@Html.DisplayNameFor(model => model.Stores.StoreArea)*@  
  23.                 </th>  
  24.             <th>  
  25.                 Distrito @*@Html.DisplayNameFor(model => model.Stores.Districts)*@  
  26.             </th>  
  27.             <th>  
  28.                 Cadena @*@Html.DisplayNameFor(model => model.Stores.StoreChains)*@  
  29.             </th>  
  30.             <th></th>  
  31.         </tr>  
  32.     </thead>  
  33.     <tbody>  
  34. @foreach (var item in Model) {  
  35.         <tr>  
  36.             <td>  
  37.                 @Html.DisplayFor(modelItem => item.StoreName)  
  38.             </td>  
  39.             <td>  
  40.                 @Html.DisplayFor(modelItem => item.StoreAddress)  
  41.             </td>  
  42.             <td>  
  43.                 @Html.DisplayFor(modelItem => item.StoreArea)  
  44.             </td>  
  45.             <td>  
  46.                 @Html.DisplayFor(modelItem => item.Districts.DistrictID)  
  47.             </td>  
  48.             <td>  
  49.                 @Html.DisplayFor(modelItem => item.StoreChains.StoreChainID)  
  50.             </td>  
  51.             <td>  
  52.                 <a asp-action="Edit" asp-route-id="@item.StoreID">Edit</a> |  
  53.                 <a asp-action="Details" asp-route-id="@item.StoreID">Details</a> |  
  54.                 <a asp-action="Delete" asp-route-id="@item.StoreID">Delete</a>  
  55.             </td>  
  56.         </tr>  
  57. }  
  58.     </tbody>  
  59. </table>  
  60.   
  61. <form asp-controller="StoresGlobal" asp-action="Index" method="post" class="form-horizontal" role="form">  
  62.     <div class="form-group">  
  63.         <div class="row">  
  64.             <div class="alert-danger" aspp-validation-summary="ModelOnly"></div>  
  65.             <div class="col-xs-12 col-sm-6 col-md-6 col-lg-4">  
  66.                 <label asp-for="DepartmentName" class="control-label"></label>  
  67.                 <select asp-for="DepartmentID"  
  68.                         class="form-control"  
  69.                         asp-items="@(new SelectList(ViewBag.ListofDepartment,"DepartmentID","DepartmentName"))"></select>  
  70.             </div>  
  71.         </div>  
  72.     </div>  
  73. </form>  
 Ok, so, yes, this is not working because I'm using a Store model in the Index:
  1. @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:
  1.   public class StoreLocationViewModel  
  2.   {  
  3. public Store Stores { getset; }  
  4. public Department Departments { getset; }  
  5.   }  
 With this, I would have to change my Index model like this: 
  1. @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: 
  1. var plataformaContext = _context.Stores.Include(c => c.StoreChains).Include(s => s.Districts)  
  2.                 .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. 
 
 
 
 

Answers (1)