I am new to MVC and still learning my ways, and I am trying to fill up a drop down list. I have the following code (Model):
public class SchoolCodes
{
public int escuelaCode { get; set; }
public string escuelaName { get; set; }
}
public class AllSchoolCodes
{
public List<SchoolCodes> GetSchools()
{
List<SchoolCodes> Codes = new List<SchoolCodes>();
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MCE"].ConnectionString);
SqlCommand comm = new SqlCommand("SELECT EscuelaCode, EscuelaName from Escuelas", conn);
conn.Open();
using (var dataReader = comm.ExecuteReader())
{
while (dataReader.Read())
{
SchoolCodes ur = new SchoolCodes();
ur.escuelaCode = Convert.ToInt32(dataReader["EscuelaCode"]);
ur.escuelaName = Convert.ToString(dataReader["EscuelaName"]);
Codes.Add(ur);
}
}
return Codes;
}
}
public class GetSchoolCodeViewModel
{
[Display(Name = "Escuela: ")]
public int SelectedEscuelaCode { get; set; }
public IEnumerable<SelectListItem> AllSchoolCodes { get; set; }
}
Controller:
private IEnumerable<SelectListItem> GetCode()
{
var dbSchoolCodes = new AllSchoolCodes();
var code = dbSchoolCodes
.GetSchools()
.Select(x =>
new SelectListItem
{
Value = x.escuelaCode.ToString(),
Text = x.escuelaName
});
return new SelectList(code, "Value", "Text");
}
public ActionResult Index()
{
var model = new GetSchoolCodeViewModel
{
AllSchoolCodes = GetCode()
};
return View(model);
// return View();
}
Now, I am getting the following error back there in the Index controller : Error 1 Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?). I am stuck here and have absolutely no idea what to do. Any help would be awesome.
Ypu don't need to create SelectListagain as you are reutrning IEnumerable<SelectListItem> , you can simply return SelectList this way:
private SelectList GetCode()
{
var dbSchoolCodes = new AllSchoolCodes();
var code = dbSchoolCodes.GetSchools();
return new SelectList(code, "escuelaCode", "escuelaName");
}
or if you want to return IEnumerable<SelectListItem> then you can do this way no need to create SelectList again:
private IEnumerable<SelectListItem> GetCode()
{
var dbSchoolCodes = new AllSchoolCodes();
var code = dbSchoolCodes
.GetSchools()
.Select(x =>
new SelectListItem
{
Value = x.escuelaCode.ToString(),
Text = x.escuelaName
});
return code;
}
Related
I'm trying to bind the dropownlist values from a database by using the below code, but it throwing error in view. I did the multiple exercises but couldn't reach the output. Can someone please help me with this?
Error:
There is no ViewData item of type 'IEnumerable' that has the key 'LocID'.'
Action Code:
public ActionResult Add()
{
List<Location> listObj = new List<Location>();
{
listObj = LocDrpDwnList();
};
List<SelectListItem> LocList = new List<SelectListItem>();
foreach(var item in listObj)
{
LocList.Add(new SelectListItem
{
Text = item.LocationName.ToString(),
Value = Convert.ToInt32(item.LocID).ToString()
}) ;
}
ViewBag.LocID = LocList;
return View();
}
Method to get the List Values from Database:
public List<Location> LocDrpDwnList()
{
SqlConnection db = new SqlConnection(conn);
string query = "SELECT * FROM Location";
SqlCommand cmd = new SqlCommand(query, db);
db.Open();
List<Location> loclist = new List<Location>();
using (IDataReader dataReader = cmd.ExecuteReader())
{
while (dataReader.Read())
{
Location obj = new Location();
if (dataReader["LocID"] != DBNull.Value)
{
if (dataReader["LocID"] != DBNull.Value) { obj.LocID = Convert.ToInt32(dataReader["LocID"]); }
if (dataReader["LocationName"] != DBNull.Value) { obj.LocationName = (string)dataReader["LocationName"]; }
loclist.Add(obj);
}
}
return loclist;
}
}
View for the Dropdown Control:
#Html.DropDownListFor(model => model.LocID, (IEnumerable<SelectListItem>)ViewBag.LocID , "Select Location", new { htmlAttributes = new { #class = "form-control" } })
Please modify your controller action as:
public ActionResult Add()
{
List<Location> listObj = LocDrpDwnList();
/*
// Doesn't hurt populating SelectListItem this way. But you don't need to do this here.
List<SelectListItem> LocList = new List<SelectListItem>();
foreach (var item in listObj)
{
LocList.Add(new SelectListItem
{
Text = item.LocationName.ToString(),
Value = Convert.ToInt32(item.LocID).ToString()
});
}
*/
ViewBag.LocID = (string?)null; //Set to some predefined locId selection, so when page is loaded, dropdown will be defaulted to this value.
ViewBag.LocList = LocList;
return View();
}
and then update your view as:
#{
var LocList = new SelectList(ViewBag.LocList, "Id", "Text");
string LocId = ViewBag.LocId ?? (string)null;
}
#Html.DropDownList(#LocId, #LocList , "Select Location", new { htmlAttributes = new { #class = "form-control" } })
Instead of using ViewBags, its good practice to use ViewModels like something below:
public class AddViewModel
{
public AddViewModel()
{
this.LocList = new List<LocationViewModel>();
}
public int? LocId { get; set; }
// Instead of LocationViewModel, you can go with your idea List<SelectListItem> and change controller action and view accordingly.
public List<LocationViewModel> LocList { get; set; }
}
public class LocationViewModel
{
public int LocId { get; set; }
public string LocationName { get; set; }
}
and your controller action will be:
public ActionResult Add()
{
List<Location> listObj = LocDrpDwnList();
List<LocationViewModel> LocList = new List<LocationViewModel>();
foreach (var item in listObj)
{
LocList.Add(new LocationViewModel
{
LocationName = item.LocationName.ToString(),
LocId = Convert.ToInt32(item.LocID).ToString()
});
}
/*
ViewBag.LocID = (string?)null; //Set to some predefined locId selection, so when page is loaded, dropdown will be defaulted to this value.
ViewBag.LocList = LocList;*/
return View(new AddViewModel{LocList = LocList});
}
and your view will be;
#using AddViewModel
#Html.DropDownList(m => m.LocId, new SelectList(Model.#LocList, "Id", "Text") , "Select Location", new { htmlAttributes = new { #class = "form-control" } })
I believe you are trying to create a entry in a Database after selecting a Value from a DROP DOWN LIST, If i'm not wrong your mentioned code of a Controller is not having the POST header, you have to create another Controller with the same name with {HttpPost} hearder.
Kindly find the below link for your reference, may be you will find any sort of help.
https://stackoverflow.com/questions/51551547/asp-mvc-model-entity-validation-does-not-displaying-required-error
I have two DbSets:
public DbSet<Reports.Models.Application> Application { get; set; }
public DbSet<Reports.Models.Category> Category { get; set; }
In the controller, I'm creating two List<SelectListItem>s:
var applications = _context.Application
.Select(listItem => new SelectListItem
{
Value = listItem.ID,
Text = listItem.Name
}
).ToList();
var categories = _context.Category
.Select(listItem => new SelectListItem
{
Value = listItem.ID,
Text = listItem.Name
}
).ToList();
I'd like to refactor this into a single, private method:
private List<SelectListItem> SelectList<T>(bool blankListItem = false)
{
var selectListItems = _context.<T> <------ doesn't compile
.Select(listItem => new SelectListItem
{
Value = listItem.ID,
Text = listItem.Name
}
).ToList();
if (blankListItem)
selectListItems.Insert(0, (new SelectListItem { Text = $"Choose {{T.ToString}}", Value = "" }));
return selectListItems;
}
And call it twice:
var applications = SelectList<Application>();
var categories = SelectList<Category>();
or
var applications = SelectList<Application>(true); // add "choose"
var categories = SelectList<Category>(true); // add "choose"
What's the right way to define the _context.<T> part? Perhaps this should be an extension method of the DbSet instead?
Maybe you can have your dbsets inherit a base class. which would be representing the generic type T.
Something like;
public class BaseClassForDbSets
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Application : BaseClassForDbSets
{
}
public class Category : BaseClassForDbSets
{
}
and then your private method;
private IEnumerable<SelectListItem> GetSelectList<T>(IEnumerable<T> dataSource, bool blankListItem = false) where T : BaseClassForDbSets
{
var selectListItems = dataSource
.Select(listItem => new SelectListItem
{
Value = listItem.Id.ToString(),
Text = listItem.Name
}
).ToList();
if (blankListItem)
selectListItems.Insert(0, (new SelectListItem { Text = $"Choose {nameof(T)}", Value = "" }));
return selectListItems;
}
Then you would call it like;
var applicationCollection = GetSelectList(_context.Application);
var categoryCollection = GetSelectList(_context.Category);
Do note - not tested
My solution uses a different approach, but same result.
Start with an interface:
public interface IBaseSelectItem
{
int Id { get; set; }
string Name { get; set; }
}
Have your entities (Application and Category) implement the interface:
public partial class Category : IBaseSelectItem
{
public int Id { get; set; }
public string Name { get; set; }
}
Create an extension on DbSet:
public static IList<SelectListItem> AsSelectList<T>(this DbSet<T> dbSet, bool useChooseValueOption) where T : class, IBaseSelectItem
{
var selectList = dbSet
.Select(c => new SelectListItem { Value = c.Id.ToString(), Text = c.Name })
.ToList();
if (useChooseValueOption)
selectList.Insert(0, new SelectListItem { Value = "0", Text = "-Choose Value-" });
return selectList;
}
Then use like this:
var categoriesSelectList = _dbContext.Categories.AsSelectList();
my Model is
public class ChildMenu
{
public string Name { get; set; }
public string Comments { get; set; }
public List<UlrikenModel.ulriken_tblChildMenu> FormDetails { get; set; }
public long pkChildMenuID { get; set; }
public long fkSubMenuID { get; set; }
[Required(ErrorMessage = "Requird")]
public string ChildManuName { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime ModifiedDate { get; set; }
public string Events { get; set; }
public IList<SelectListItem> Drp_Submenu { get; set; }
}
My Controller action is :
public ActionResult FillDeptName()
{
UlrikenEntities db1 = new UlrikenModel.UlrikenEntities();
List<SelectListItem> list = new List<SelectListItem>();
list.Add(new SelectListItem { Text = "-Please select-", Value = "Selects
items" });
var cat = (from c in db1.ulriken_tblSubMenu where c.fkMainMenuID == 1 &&
c.Status == true select new { c.pkSubMenuID,c.SubManuName }).ToArray();
for (int i = 0; i < cat.Length; i++)
{
list.Add(new SelectListItem
{
Text = cat[i].SubManuName,
Value = cat[i].pkSubMenuID.ToString(),
Selected = (cat[i].pkSubMenuID == 1)
});
}
ViewBag.list = list;
return View("ChildMenuOfSubMenu", ViewBag.list);
}
[HttpPost]
[ValidateInput(false)]
public ActionResult ChildMenuOfSubMenu(ChildMenu obj)
{
UlrikenEntities db = new UlrikenEntities();
ulriken_tblChildMenu objchild = new ulriken_tblChildMenu();
objchild.fkSubMenuID = obj.fkSubMenuID;
objchild.ChildMenuName = obj.ChildManuName;
objchild.cPageBody = obj.Name;
db.ulriken_tblChildMenu.Add(objchild);
db.SaveChanges();
return View("ChildMenuOfSubMenu");
}
and view is
#Html.DropDownListFor(m=>m.fkSubMenuID,
(IEnumerable<SelectListItem>)ViewBag.list,"Select" ,new { id = "ddlSubMenu" })
At start dropdown bind successfully but after saving data to database show an exception in
as "There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key
'fkSubMenuID'"
AnyBody guide me where am i doing wrong.
Move that code to the helper class:
public class ControllerHelper
{
public List<SelectListItem> FetchListItems()
{
List<SelectListItem> list = new List<SelectListItem>();
list.Add(new SelectListItem { Text = "-Please select-", Value = "Selects items" });
var cat = (from c in db1.ulriken_tblSubMenu where c.fkMainMenuID == 1 &&
c.Status == true select new { c.pkSubMenuID,c.SubManuName }).ToArray();
for (int i = 0; i < cat.Length; i++)
{
list.Add(new SelectListItem
{
Text = cat[i].SubManuName,
Value = cat[i].pkSubMenuID.ToString(),
Selected = (cat[i].pkSubMenuID == 1)
});
}
return list;
}
}
And then your controller should looks like:
public ActionResult FillDeptName()
{
UlrikenEntities db1 = new UlrikenModel.UlrikenEntities();
ViewBag.list = new ControllerHelper().FetchListItems();
return View("ChildMenuOfSubMenu", ViewBag.list);
}
[HttpPost]
[ValidateInput(false)]
public ActionResult ChildMenuOfSubMenu(ChildMenu obj)
{
UlrikenEntities db = new UlrikenEntities();
ulriken_tblChildMenu objchild = new ulriken_tblChildMenu();
objchild.fkSubMenuID = obj.fkSubMenuID;
objchild.ChildMenuName = obj.ChildManuName;
objchild.cPageBody = obj.Name;
db.ulriken_tblChildMenu.Add(objchild);
db.SaveChanges();
ViewBag.list = new ControllerHelper().FetchListItems();
return View("ChildMenuOfSubMenu");
}
Of course:
new ControllerHelper().FetchListItems();
should be a field in the controller class, for example:
private ControllerHelper controlerHelper;
You can use Interface instead of concerete implementation, if you use DI.
Regards
I have a table in my database which I select all Mem_NA to fill it in my dropdownlist in my view.
I can't understand how can I fill the values in there? Someone can give me a hand?
My Model
public class MemberBasicData
{
public int Id { get; set; }
public string Mem_NA { get; set; }
public string Mem_Occ { get; set; }
}
public List<MemberBasicData> GetAllMembers()
{
DateTime today = DateTime.Now;
List<MemberBasicData> mbd = new List<MemberBasicData>();
using (SqlConnection con = new SqlConnection(Config.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("SELECT Id,Mem_NA,Mem_Occ FROM Mem_Basic", con))
{
try
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
MemberBasicData mb = new MemberBasicData();
mb.Id = (int)reader["Id"];
mb.Mem_NA = (string)reader["Mem_NA"];
mb.Mem_Occ =(string)reader["Mem_Occ"];
mbd.Add(mb);
}
}
catch (Exception e)
{
throw e;
}
finally
{
if (con.State == System.Data.ConnectionState.Open)
{
con.Close();
}
}
return mbd;
}
}
}
GetAllMembers() function is an IEnumerable function which I was used for get all details of members. Can I use the same function for filling the dropdown list?
My controller
public ActionResult Register()
{
return View(new Member());
}
And View
#Html.DropDownListFor("-- Select --", new SelectList("")) <=== ???? i dont know
Model
public MemberModel
{
List<SelectListItem> MemberList { get; set; }
}
Controller
public ActionResult Register()
{
MemberModel model = new MemberModel();
model.MemberList = GetAllMembers()
.Select(m => new SelectListItem
{
Text = string.format("{0}, {1}", m.Mem_NA, m.Mem_Occ),
Value = m.Id
});
SelectListItem default = new SelectListItem
{
Text = "-- SELECT --",
Value = 0
};
model.MemberList.Insert(0, default);
return View(model);
}
View
#Html.DropDownList(Model.MemberList);
UPDATE: This version adds a default entry to the beginning of the list.
#Html.DropDownListFor gets an IEnumerable of SelectListItem. But instead, you want to use a list of MemberBasicData. You must convert your MemberBasicData list to SelectListItem and pass it to the #Html.DropDownListFor instead of a list of MemberBasicData. For passing related data to the Views as Sirwan pointed, you can use ViewBag or ViewData.
Having a hard time getting this dropDownList to Bind. This is simply a list of states. The Model.State is "TX", but my dropdownlist is showing "AK", which is the first value in the list. Any thoughts?
<%: Html.DropDownListFor(
model => model.State,
new SelectList(
muniSynd.getStatecodesDropDown(),
"Value",
"Text",
Model.State.ToString().Trim()
)
)
%>
In my muniSynd class, which is a wrapper of my dataContext.....
public IList<StateCodeViewModel> getStatecodesDropDown()
{
var states = from p in this._MuniDc.Statecodes
select new StateCodeViewModel
{
Value = p.Statecode1.ToString().Trim(),
Text = p.Statecode1.ToString().Trim()
};
return states.ToList();
}
public class StateCodeViewModel
{
public string Value{get;set;}
public string Text{get;set;}
}
Im using LinqToSQL, here is the object
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Statecodes")]
public partial class Statecode
{
private string _Statecode1;
public Statecode()
{
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Name="Statecode", Storage="_Statecode1", DbType="NVarChar(3)")]
public string Statecode1
{
get
{
return this._Statecode1;
}
set
{
if ((this._Statecode1 != value))
{
this._Statecode1 = value;
}
}
}
}
I've tried to replicate your problem, but my example below works fine:
public class HomeController : Controller
{
public ActionResult Index()
{
var viewModel = new IndexViewModel();
viewModel.State = "TX";
return this.View(viewModel);
}
public static IList<StateCodeViewModel> getStatecodesDropDown()
{
var stateCodes = new List<string> { "AX", "GH", "TX" };
var states = from p in stateCodes
select new StateCodeViewModel
{
Value = p,
Text = p
};
return states.ToList();
}
}
public class IndexViewModel
{
public string State { get; set; }
}
public class StateCodeViewModel
{
public string Value { get; set; }
public string Text { get; set; }
}
View
#using MVCWorkbench.Controllers
#model IndexViewModel
#{
ViewBag.Title = "title";
}
#Html.DropDownListFor(model => model.State,
new SelectList(HomeController.getStatecodesDropDown(),
"Value",
"Text",
Model.State.ToString().Trim()
)
)
Not sure what to suggest other then check that the State value is in the dropdown list. Also this could be a case-sensitivity issue perhaps?