Why is this not working?
I feel like I am losing my mind.
I am using asp.net core with entity frameworks. This code in my controller is not working. I just want to return the ChildLans where the ParentOrgLevel contains 0001 at the beginning.
Model
public class CORP_MatrixPositionOLDWay
{
public int ID { get; set; }
public string ParentLAN { get; set; }
public string ChildLAN { get; set; }
public string ChildOrgLevel { get; set; }
public string ParentOrgLevel { get; set; }
}
View
model IEnumerable<Certifications.Models.CORP_MatrixPositionOLDWay>
#{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.ParentOrgLevel)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ParentOrgLevel)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="#item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="#item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Controller
public async Task<IActionResult> Index()
{
var ParentORG = _context.CORP_MatrixPositionOLDWay
.Where(i => i.ParentLAN == UserInformation.Globals.LANID)
.Select(i => i.ParentOrgLevel);
return View(ParentORG);
}
UserInformation.Globals.LANID is a string variable for the machines LANID
You are missing a lambda in your Where(), you can also just use StartsWith() instead of Contains() if you want to be more specific:
var list = _context.CORP_MatrixPositionOLDWay
.Where(x => x.ParentOrgLevel.StartsWith("0001"))
.Select(x => x.ChildLAN);
Given your latest edit
Your view expects a model of IEnumerable<Certifications.Models.CORP_MatrixPositionOLDWay>
Your action must return a View with that type as a model:
public async Task<IActionResult> Index()
{
var ParentORG = _context.CORP_MatrixPositionOLDWay
.Where(i => i.ParentLAN == UserInformation.Globals.LANID);
return View(ParentORG);
}
If you want your view to have only the ChildLAN properties (as you indicated in your comment below) then you'll have to adjust your view's model to be of type IEnumerable. However keep in mind that by doing this you will lose all the other functionality of your view (since its dependent on other properties of the CORP_MatrixPositionOLDWay class. What you likely want to do is create a new class called IndexViewModel or something like that. and have it contain both things you need:
public class IndexViewModel
{
//Name these properties better than I have
public IEnumerable<string> ChildLans {get;set;}
public IEnumerable<CORP_MatrixPositionOLDWay> DataList {get;set;}
}
Related
I am trying build a project while self learning but have been stuck in one place.
I have this class Roles:
namespace IC2021.Models
{
public partial class Roles
{
public Roles()
{
Staffs = new HashSet<Staffs>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Staffs> Staffs { get; set; }
}
}
And another called Staffs:
namespace IC2021.Models
{
public partial class Staffs
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Location { get; set; }
public int? RoleId { get; set; }
public string Archived { get; set; }
public virtual Roles Role { get; set; }
}
}
This is my RolesController:
namespace IC2021.Controllers
{
public class RolesController : Controller
{
private readonly ICOctober2021Context _context;
public RolesController(ICOctober2021Context context)
{
_context = context;
}
// GET: Roles
public async Task<IActionResult> Index()
{
return View(await _context.Roles.ToListAsync());
}
public async Task<IActionResult> RolesWithStaffs()
{
var iCOctober2021Context = _context.Roles.Include(s => s.Staffs);
return View(await iCOctober2021Context.ToListAsync());
}
}
}
And finally I'm trying to view it from RolesWithStaffs:
<!-- model declaration -->
#model IEnumerable<IC2021.Models.Roles>
#{
ViewData["Title"] = "RolesWithViewController";
}
<h1>RolesWithViewController</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
Role
</th>
<th>
Staff Name
</th>
<th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Id)
</td>
<td>
#Html.DisplayFor(modelItem => item.Staffs)
</td>
#*<td>
<a asp-action="Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="#item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</td>*#
</tr>
}
</tbody>
</table>
So here in the view when I tried to access from Staffs, I am not able (for example item.Staffs.FirstName, or anything else from Staffs). Whereas I can do it other way, I mean from staffs view I can access Roles.Name or Id).
Can anyone please help me? Any help will be highly appreciated.
Your view model looks quite unusual, IMHO you can try this
public async Task<IActionResult> RolesWithStaffs()
{
var model= await _context.Set<Staffs>().Include(s => s.Role).ToListAsync();
return View(model);
}
and view
<table class="table">
<thead>
<tr>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Role
</th>
<th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(item=> item.FirstName)
</td>
<td>
#Html.DisplayFor(item=> item.LastName)
</td>
<td>
#Html.DisplayFor(item => item.Role.Name)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="#item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Could you please help me, To get multiple table data as list from view controller using view model. Below is my Code Its Working till passing multiple model to View. I am not able to get those updated values from View in controller Action Method to Update the data.
I have Two Models.
public class Teacher
{
public int TeacherId { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
public class Student
{
public int StudentId { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
Pass those Model in a model as list
public class ViewModel
{
public IEnumerable<Teacher> Teachers { get; set; }
public IEnumerable<Student> Students { get; set; }
}
In Controller, I have define the View Model
[HttpGet]
public ActionResult IndexViewModel()
{
ViewModel mymodel = new ViewModel();
mymodel.Teachers = GetTeachers();
mymodel.Students = GetStudents();
return View(mymodel);
}
In My View, I have all the values correctly but when I change the value same submit. the updated data is not able to get on action method. Please Help me on this.
#using MultipleModelInOneView;
#model ViewModel
#{
ViewBag.Title = "Home Page";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<table>
<tr>
<th>Id</th>
<th>Code</th>
<th>Name</th>
</tr>
#foreach (Teacher teacher in Model.Teachers)
{
<tr>
<td>#Html.DisplayFor(model => #teacher.TeacherId)</td>
<td>#Html.EditorFor(model => #teacher.Code)</td>
<td>#Html.EditorFor(model => #teacher.Name)</td>
</tr>
}
</table>
<p><b>Student List</b></p>
<table>
<tr>
<th>Id</th>
<th>Code</th>
<th>Name</th>
<th>Enrollment No</th>
</tr>
#foreach (Student student in Model.Students)
{
<tr>
<td>#Html.DisplayFor(model => #student.StudentId)</td>
<td>#Html.EditorFor(model => #student.Code)</td>
<td>#Html.EditorFor(model => #student.Name)</td>
</tr>
}
</table>
<input type="submit" value="Save" class="btn btn-primary" />
}
Here I am Not able to Get List from View
[HttpPost]
public ActionResult IndexViewModel("Here I'm not able to Get List from View")
{
return View();
}
try to replace foreach loop by for loop
#for (var i=0; i < Model.Teachers.Count; i+=1)
{
<tr>
<td>#Html.DisplayFor(model =>model.Teachers[i].TeacherId)</td>
<td>#Html.EditorFor(model => model.Teachers[i].Code)</td>
<td>#Html.EditorFor(model => model.Teachers[i].Name)</td>
</tr>
}
#for (var i=0; i < Model.Students.Count; i+=1)
{
<tr>
<td>#Html.DisplayFor(model => model.Students[i].StudentId)</td>
<td>#Html.EditorFor(model => model.Students[i].Code)</td>
<td>#Html.EditorFor(model => model.Students[i].Name)</td>
</tr>
}
and the controller action
public ActionResult IndexViewModel(ViewModel viewModel)
{
....
}
When passing ViewModel to View I get the error
The model item passed into the ViewDataDictionary is of type
'System.Collections.Generic.List'1[TraficAlert.Models.TaBarHeader]',
but this ViewDataDictionary instance requires a model item of type
'System.Collections.Generic.IEnumerable'1[TraficAlert.Models.ViewModels.HeaderTelegramaViewModel]'.
I have tried to use #model IEnumerable<TraficAlert.Models.ViewModels.HeaderTelegramaViewModel> in the Index.cshtml and it works, but I need to access a property from HeaderTelegramaViewModel.
Index.cshtml:
#model IEnumerable<TraficAlert.Models.ViewModels.HeaderTelegramaViewModel>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.TaBarHeader.Id)
</th>
<th>
#Html.DisplayNameFor(model => model.TaBarHeader.ParentId)
</th>
<th>
#Html.DisplayNameFor(model => model.TaBarHeader.TStamp)
</th>
(...)
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.TaBarHeader.Id)
</td>
<td>
#Html.DisplayFor(modelItem => item.TaBarHeader.ParentId)
</td>
<td>
#Html.DisplayFor(modelItem => item.TaBarHeader.TStamp)
</td>
(...)
<td>
<a asp-action="Edit" asp-route-id="#item.TaBarHeader.Id">Edit</a> |
<a asp-action="Details" asp-route-id="#item.TaBarHeader.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.TaBarHeader.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
HeaderTelegramaController:
(...)
public IActionResult Index()
{
var applicationDbContext = _unitofwork.BarHeader.GetAllBarH().ToList();
return View(applicationDbContext);
}
TaBarHeaderRepository:
public IEnumerable<TaBarHeader> GetAllBarH()
{
return _db.TaBarHeaders
.Include(t => t.CategoriaFk)
.Include(t => t.CauzaFk)
.Include(t => t.ClasaFk)
.Include(t => t.LucrareFk)
.Include(t => t.RegionalaFk)
.Include(t => t.UserFk);
}
HeaderTelegramaViewModel:
public TaBarHeader TaBarHeader { get; set; }
public IEnumerable<SelectListItem> Categoria { get; set; }
public IEnumerable<ViewOtf> ViewOTFCollection { get; set; }
(...)
Why do I get the above mentioned error?
Thank you.
use the model below in the cshtml.
#model TraficAlert.Models.ViewModels.HeaderTelegramaViewModel
And in the Index() create an instance of HeaderTelegramaViewModel:
var _HeaderTelegramaViewModel = new HeaderTelegramaViewModel();
_HeaderTelegramaViewModel.TaBarHeader = TaBarHeader;
And the class HeaderTelegramaViewModel must have:
public IEnumerable<TaBarHeader> TaBarHeader { get; set; }
public IEnumerable<SelectListItem> Categoria { get; set; }
public IEnumerable<ViewOtf> ViewOTFCollection { get; set; }
use :: #model TraficAlert.Models.ViewModels.HeaderTelegramaViewModel
instead of ::#model IEnumerable<TraficAlert.Models.ViewModels.HeaderTelegramaViewModel>
at the top of index.cshtml page
See the type of your model IEnumerable<TraficAlert.Models.ViewModels.HeaderTelegramaViewModel> and apply this:
public IActionResult Index()
{
var applicationDbContext = _unitofwork.BarHeader.GetAllBarH();
return View(applicationDbContext);
}
The error message explains the problem fairly clearly: you're passing in a different type than the view is expecting.
Specifically, you call GetAllBarH() to get the data for the view, and it returns IEnumerable<TaBarHeader>. Therefore the model declaration for the page should be:
#model IEnumerable<TraficAlert.Models.TaBarHeader>
If you really wanted HeaderTelegramaViewModel then you're going to have to convert the IEnumerable<TaBarHeader> somehow. I assume you missed that step in your controller.
Why do I get the above mentioned error?
Because the data type returned in your action is not the same as the data type required on the view.
You can modify your HeaderTelegramaController like this:
public IActionResult Index()
{
var applicationDbContext = _unitofwork.BarHeader.GetAllBarH().Select(m => new HeaderTelegramaViewModel { TaBarHeader = m }).ToList();
return View(applicationDbContext);
}
A possible error I assume may come from your table head
try specifying an index considering your model is an IEnumerable.
So change
#Html.DisplayFor(modelItem => item.TaBarHeader.Id)
to something like this
#Html.DisplayFor(modelItem => item[0].TaBarHeader.Id)
I am working on a "Survey" application in MVC 5. Basically it's an application to support surveys for users to fill out. The user can also go back at any time later on and change their answer too.
UI: I have a table with each row containing the actual survey questions, their answer (Yes/No/N-A, from a dropdownlistfor) and row-based comments. Their answer (dropdownlist selection) and comments for each row should be the POST vars submitted to the action.
Problem: I'm having trouble getting any post variables, which are always null. Here's some of my code...
ViewModel (SurveyResultsViewModel.cs)
[NotMapped]
public class SurveyResultsViewModel
{
// ------ hidden
[Key]
public int EventId { get; set; }
[Display(Name = "Category")]
public string SurveyCategory { get; set; }
[Display(Name = "Question")]
public string SurveyQuestionText { get; set; }
public int SurveyQuestionId { get; set; }
public SelectList SurveyAnswerOption { get; set; }
public int SurveyResultsId { get; set; }
[Display(Name = "Answer")]
public string SelectedSurveyAnswer { get; set; }
public string Comments { get; set; }
}
Controller GET...
public ActionResult Index(int id)
{
:
:
:
List<SurveyResultsViewModel> vm = new List<SurveyResultsViewModel>();
var Surveyresults = db.SurveyResults
.Where(i => i.EventId == id)
.Include(a => a.SurveyQuestion)
.OrderBy(a=>a.SurveyQuestion.SurveyQuestionCategory.Id)
.Include(a => a.Event);
foreach (SurveyResult ar in Surveyresults)
{
var newVmRecord = new SurveyResultsViewModel();
newVmRecord.EventId = id;
newVmRecord.SurveyAnswerOption = new SelectList(db.SurveyAnswerOptions, "AnswerOptionText", "AnswerOptionText", ar.SurveyAnswer);
newVmRecord.SurveyCategory = ar.SurveyQuestion.SurveyQuestionCategory.SurveyQuestionCategory1;
newVmRecord.SurveyQuestionId = ar.SurveyQuestionId.Value;
newVmRecord.SurveyQuestionText = ar.SurveyQuestion.SurveyQuestionText;
newVmRecord.Comments = ar.Comments;
newVmRecord.SelectedSurveyAnswer = ar.SurveyAnswer;
newVmRecord.SurveyResultsId = ar.Id;
vm.Add(newVmRecord);
}
return View(vm.ToList());
}
Here's part of my View....
#model IEnumerable<SurveyApp.ViewModels.SurveyResultsViewModel>
:
:
<div class="ibox-content">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<table class="table table-striped">
<tr>
<th class="col-md-2">
#Html.DisplayNameFor(model => model.SurveyCategory)
</th>
<th class="col-md-5">
#Html.DisplayNameFor(model => model.SurveyQuestionText)
</th>
<th>
#Html.DisplayNameFor(model => model.SelectedSurveyAnswer)
</th>
<th>
#Html.DisplayNameFor(model => model.Comments)
</th>
</tr>
#{
int i = 0;
}
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.SurveyCategory)
</td>
<td>
#Html.DisplayFor(modelItem => item.SurveyQuestionText)
</td>
<td>
#Html.TextBoxFor(modelItem => item.SelectedSurveyAnswer)
#Html.DropDownListFor(modelItem => item.SelectedSurveyAnswer, item.SurveyAnswerOption, "--Select--")
</td>
<td>
#Html.HiddenFor(modelItem => item.SurveyResultsId)
#Html.TextAreaFor(modelItem => item.Comments)
</td>
</tr>
i++;
}
</table>
<input type="submit" value="Save" class="btn btn-primary"/>
#Html.ActionLink("Cancel", "Index", null, new {#class = "btn btn-white"})
}
</div>
The view appears to be displaying correctly. But, when I view source, I noticed that, when rendered, unique NAME values are not given for the "post"-related controls. I'm thinking that this may be contributing to the issue? For example, here's the rendering for one of the dropdownlistfor's....
<select id="item_SelectedSurveyAnswer" name="item.SelectedSurveyAnswer">
<option value="">--Select--</option>
<option selected="selected" value="Yes">Yes</option>
<option value="No">No</option>
<option value="N/A">N/A</option>
</select>
Here's my preliminary POST method. The var mySurveyResult is always NULL...
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(
//[Bind(Include = "SurveyResultsId,SelectedSurveyAnswer,Comments")]
List<SurveyResultsViewModel> mySurveyResult)
{
if (ModelState.IsValid)
{
for (int i = 0; i < mySurveyResult.Count(); i++)
{
Console.WriteLine(mySurveyResult[i].SelectedSurveyAnswer);
}
db.Entry(mySurveyResult).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View();
}
As you can see I haven't fully written this method yet. But, essentially, this post action will need to loop through each answer posted and save it to the db. I haven't gotten that far yet because I keep getting null for the post parameter.
Again, I'm thinking that the problem may be that there are no unique name attributes maybe? Maybe this is affecting the POST? Any feedback would be appreciated. Also, if you see (from my posted code examples) that I'm not doing things correctly please let me know.
Please let me thank you in advance!
You need to use for rather than foreach to iterate over your items:
#for (var i = 0; i < Model.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(modelItem => Model[i].SurveyCategory)
</td>
<td>
#Html.DisplayFor(modelItem => Model[i].SurveyQuestionText)
</td>
<td>
#Html.TextBoxFor(modelItem => Model[i].SelectedSurveyAnswer)
#Html.DropDownListFor(modelItem => Model[i].SelectedSurveyAnswer, Model[i].SurveyAnswerOption, "--Select--")
</td>
<td>
#Html.HiddenFor(modelItem => Model[i].SurveyResultsId)
#Html.TextAreaFor(modelItem => Model[i].Comments)
</td>
</tr>
}
This will give your fields names like [0].SelectedSurveyAnswer, instead of just SelectedSurveyAnswer, allowing the modelbinder to actually be able to bind the posted values back to a list.
I couldn't find a solution for my issue, I have tried many alternatives but I could not resolve it.
I generate my database with the model first, afterwards I have used Scaffolding to generate the Views (Index, Create, Edit, Delete..). The only view (Index) with the model use IEnumerable.
The Index View was :
#model IEnumerable<CAD_CMDBv2.Models.Location>
#{
ViewBag.Title = "Location's Management";
}
<h2>All Locations</h2>
<p>
#Html.ActionLink("Create Location", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Location.site_name)
</th>
<th>
#Html.DisplayNameFor(model => model.Location.country_name)
</th>
<th>
#Html.DisplayNameFor(model => model.Location.region_name)
</th>
<th></th>
</tr>
#foreach(var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Location.site_name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Location.country_name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Location.region_name)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Location.location_id }) |
#Html.ActionLink("Details", "Details", new { id = item.Location.location_id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Location.location_id })
</td>
</tr>
}
</table>
I want to insert an asynchronous form for the datasearch, so that becomes:
#model IEnumerable<CAD_CMDBv2.Models.RechercheLocationViewModel>
#{
ViewBag.Title = "Location's Management";
}
<h2>All Locations</h2>
<p>
#Html.ActionLink("Create Location", "Create")
</p>
#using (Html.BeginForm("Search", "Restaurant", FormMethod.Get))
{
#Html.TextBoxFor(r => r.Recherche)
<input type="submit" value="Rechercher" />
<p>Search Results </p>
if (Model.ListeLocations.Count == 0)
{
<p> No Results but you can create it !</p>
}
else
{
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Location.site_name)
</th>
<th>
#Html.DisplayNameFor(model => model.Location.country_name)
</th>
<th>
#Html.DisplayNameFor(model => model.Location.region_name)
</th>
<th></th>
</tr>
#foreach(var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Location.site_name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Location.country_name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Location.region_name)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Location.location_id }) |
#Html.ActionLink("Details", "Details", new { id = item.Location.location_id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Location.location_id })
</td>
</tr>
}
</table>
}
}
I have modified the model in adding a View Model class to allow in IndexView to take as model the View Model by taking over the parameters Locations and use the Search parameter:
//------------------------------------------------------------------------------
// <auto-generated>
// Ce code a été généré à partir d'un modèle.
//
// Des modifications manuelles apportées à ce fichier peuvent conduire à un comportement inattendu de votre application.
// Les modifications manuelles apportées à ce fichier sont remplacées si le code est régénéré.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CAD_CMDBv2.Models
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public partial class Location
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Location()
{
this.User = new HashSet<User>();
this.host = new HashSet<Host>();
this.client_catia = new HashSet<Client_catia>();
this.client_smartam = new HashSet<Client_smarteam>();
}
public int location_id { get; set; }
[Display(Name = "Site's Name")]
public string site_name { get; set; }
[Display(Name = "Country's Name")]
public string country_name { get; set; }
[Display(Name = "Region's Name")]
public string region_name { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<User> User { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Host> host { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Client_catia> client_catia { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Client_smarteam> client_smartam { get; set; }
}
public class RechercheLocationViewModel : IEnumerable<Location> {
public string Recherche {get; set;}
public Location Location { get; set; }
public List<Location> ListeLocations;
public IEnumerator<Location> GetEnumerator()
{
return ListeLocations.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ListeLocations.GetEnumerator();
}
}
}
The current Controller
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using CAD_CMDBv2.Models;
namespace CAD_CMDBv2.Areas.Locations.Controllers
{
public class LocationsController : Controller
{
private ModeleDonneesCMDBContext db = new ModeleDonneesCMDBContext();
// GET: Locations/Locations
public ActionResult Index()
{
var liste = db.Locations.ToList();
var listeTriee = liste.OrderBy(t => t.site_name);
return View(listeTriee);
}
...
But that generates two errors of the same type about IEnumerable in the Index View on the lines:
#Html.TextBoxFor(r => r.Recherche)
And
if (Model.ListeLocations.Count == 0)
I got this error:
CS1061 Error 'IEnumerable' does not contain
a definition for 'ListeLocations' and no extension method
'ListeLocations' accepting a first argument of type
'IEnumerable' could be found (are
you missing a using directive or an assembly reference ?)
What does that mean? How can I resolve this? I still have some difficulty with understanding the IEnumerable interface.
Your Location class contains the properties Recherche and ListeLocation, but an IEnumerable of that class does not have those properties.
You are using the IEnumerable of the class as an instance of that class, that can't work.
You should think about what you need your model to be, because in one part of the view you use Model as if it were a Location, and in another part (#foreach(var item in Model) {) you use it as an IEnumerable
When you use the IEnumerable interface as a model, you are telling the View you have some kind of list, collection, or something you can 'Enumerate' as a model. A list of your Location objects, so to speak, not a single one.
Edit in response to your comments:
Change the #model IEnumerable<CAD_CMDBv2.Models.RechercheLocationViewModel> to CAD_CMDBv2.Models.RechercheLocationViewModel
Then you need yo change the controller Action:
Instead of :
var liste = db.Locations.ToList();
var listeTriee = liste.OrderBy(t => t.site_name);
return View(listeTriee);
use:
var model = new RechercheLocationViewModel();
model.AddRange(db.Locations.OrderBy(t => t.site_name));
return View(model);
But that won't make it 'work':
Your search query cannot take place in the view, you will have to go back to the server for that, so the architecture of your model is not quite right; you don't need all your locations in there, an what the single Location is there for I don't understand as well. If you want to do an async search in the view, you need an AJAX call back to the server that's going to return the search result. Your form is now just going to post something back to a Search action on your controller, and I don't know what that action does.
I can only advice you to study a bit more on creating search forms with AJAX in ASP.NET MVC
This is where your error is:
var listeTriee = liste.OrderBy(t => t.site_name);
return View(listeTriee);
Instead of passing a single model to your View, you are passing a collection (IEnumerable) which indeed doesn't have the property ListeLocations.
You should create a viewmodel and put the collection in there:
public class ListeTrieeViewModel
{
...
public IEnumerable<Locations> ListeLocations {get; set;}
}
Then you can pass that model in your controller:
public ActionResult Index()
{
var liste = db.Locations.ToList();
var listeTriee = liste.OrderBy(t => t.site_name);
var viewModel = new ListeTrieeViewModel { ListeLocations = listeTriee; }
return View(viewModel);
}
Now your check in the view will work:
if (Model.ListeLocations.Count() == 0)