Fill Dropdownlist with values from sql database in MVC4 - c#

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.

Related

Populate (Bind) DropDownList from ViewModel in ASP.Net MVC using MySql

I tried to search posts, without any result either, maybe I didn't use the right words.
I need a solution in MVC for DropDownList will be populated from database using Model class and the Html.DropDownListFor Helper method.
I don't have error on Visual Studio 2019 debug, but the DropDownList is empty.
Please, help me.
My code below
Model
namespace InsGE.Models
{
public class PersonModel
{
public List<SelectListItem> Fruits { get; set; }
public string Namex { get; set; }
public string Codex { get; set; }
[Required]
[Display(Name = "CL")]
public string CL { get; set; }
[Required]
[Display(Name = "Ticket")]
public string Ticket { get; set; }
}
}
Controller
namespace InGE.Controllers
{
public class HomeController : Controller
{
private static List<SelectListItem> PopulateFruits()
{
string sql;
List<SelectListItem> items = new List<SelectListItem>();
string constr = ConfigurationManager.ConnectionStrings["cn"].ConnectionString;
using (MySqlConnection con = new MySqlConnection(constr))
{
sql = #String.Format("SELECT * FROM `dotable`; ");
using (MySqlCommand cmd = new MySqlCommand(sql))
{
cmd.Connection = con;
con.Open();
using (MySqlDataReader sdr = cmd.ExecuteReader())
{
while (sdr.Read())
{
items.Add(new SelectListItem
{
Text = sdr["sName"].ToString(),
Value = sdr["sCode"].ToString()
});
}
}
con.Close();
}
}
return items;
}
[HttpPost]
public ActionResult Index(PersonModel person)
{
string sCl = person.CL;
string sTicket = person.Ticket;
string sName = person.Namex;
string sCode = person.Codex;
PersonModel fruit = new PersonModel();
fruit.Fruits = PopulateFruits();
return View();
}
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
}
View
#Html.DropDownListFor(m => m.Fruits, Model.Fruits, "Please select")
Update
Now the debug of Visual Studio 2019 return error
System.Web.Mvc.WebViewPage<TModel>.Model.get
Object reference not set to an instance of an object error
App_Web_sxdtrbqy
in the view
#Html.DropDownListFor(m => m.Fruits, Model.Fruits, "Please select")
You should populate your model in the Index GET method and then return the model to the View passing it as its parameter.
[HttpGet]
public ActionResult Index()
{
PersonModel fruit = new PersonModel();
fruit.Fruits = PopulateFruits();
return View(fruit);
}
This is the method that will be called when you navigate to the Index page so whatever you put in the model here becomes the model in the view.
The HttpPost method is called when your user push some button or link inside a Form tag to post back the information edited in the View.

MVC dynamic dropdown list not working,getting error "There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'LocID'.'"

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

Passing Int type value via query string

I am able to successfully pass string values, but having trouble passing integer value via Query String.
If I only pass string objects the URL looks like
www.website.com/mypage?ProductName=TestName&MahName=TestName (Correct)
However, if I pass Id (int) along with the query string the URL looks like
www.website.com/mypage/1?ProductName=TestName&MahName=TestName (Incorrect)
However, I would like it to be
www.website.com/mypage?Id=1&ProductName=TestName&MahName=TestName
Model
using System.Data.SqlClient;
using System.ComponentModel.DataAnnotations;
namespace SecureMedi.Models
{
public class CustomProductData
{
[Required]
public int Id { get; set; }
[StringLength(200)]
public string ProductName { get; set; }
[StringLength(100)]
public string MahName { get; set; }
public static CustomProductData FromSqlReader(SqlDataReader rdr)
{
return new CustomProductData
{
Id = (int)rdr["id"],
ProductName = rdr["product_name"].ToString(),
MahName = rdr["mah_name"].ToString()
};
}
}
}
Controller
[HttpGet]
public ActionResult CustomProductData(int Id, string ProductName, string MahName) {
var model = new CustomProductData() {
Id = Id,
ProductName = ProductName,
MahName = MahName
};
return View(model);
}
[HttpPost]
public ActionResult CustomProductData(CustomProductData cp) {
try {
using(ISecureMediDatabase db = new SecureMediDatabase(this)) {
CustomProductDataDAL cpd = new CustomProductDataDAL(db);
cpd.Edit(cp);
return RedirectToAction("LoadCustomProductData");
}
} catch (Exception ex) {
ModelState.AddModelError("", ex.Message);
return View(cp);
}
}
DAL
public void Edit(CustomProductData cp) {
try {
string sql = "UPDATE table_name SET product_name = #ProductName, mah_name = #MahName WHERE id = #Id";
if (cp.HasDetails()) {
using(SqlCommand cmd = new SqlCommand(sql, conn)) {
cmd.Parameters.Add(new SqlParameter("#Id", cp.Id));
cmd.Parameters.Add(new SqlParameter("#ProductName", cp.ProductName));
cmd.Parameters.Add(new SqlParameter("#MahName", cp.MahName));
PrepareCommand(cmd);
cmd.ExecuteNonQuery();
}
}
} catch {
closeConnection();
throw;
}
}
cshtml
Anchor link to pass the query string values to the edit page (which take the values from the QueryString)
<td class="text-secondary">#Html.ActionLink("Edit", "CustomProductData", "Home", new { Id = #item.Id, ProductName = #item.ProductName, MahName = #item.MahName }, new { #class = "text-info" })</td>
Apparently, the variable name Id was occupied in the routing and thus changing the variable name Id to RecordId solved the issue.

Binding database to dropdownlist

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;
}

Two-Way Data Binding using jQuery Driven "Chosen" Drop Down

Alright, I have a jQuery version of Chosen applied to a select displaying properly on my page and I've done so with the following code. First I have a BaseController that sets a ViewBag property listing all of the possible categories:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
try
{
_connection.Open();
this.ViewBag.AvailableCategories = new MultiSelectList(_connection.Query<Category>("select * from Category"), "CategoryID", "Name");
}
catch (Exception ex)
{
throw new HttpException(500, ex.Message);
}
finally
{
_connection.Close();
}
base.OnActionExecuted(filterContext);
}
Next, when navigating to /Event/View/1 I have the EventController setup (NOTE this controller bases the aforementioned controller) with the following View method.
public ActionResult View(int id)
{
Event evt = null;
try
{
evt = Event.Where(_connection, id);
if (evt == null)
{
throw new HttpException(404, "Oops! The event you're looking for does not exist.");
}
}
catch (Exception ex)
{
throw new HttpException(500, ex.Message);
}
return View(evt);
}
It sets the model, as you can see, to the following model.
public class Event
{
public int EventID { get; set; }
public int BusinessID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int NeighborhoodID { get; set; }
public IEnumerable<int> CategoryIds
{
get
{
if (Categories == null) { return new List<int>(); }
return Categories.Select(c => c.CategoryID).AsEnumerable();
}
}
public List<EventCategory> Categories { get; set; }
public List<EventHours> Hours { get; set; }
public static Event Where(IDbConnection connection, int id)
{
Event result = null;
try
{
connection.Open();
var sql =
#" select * from Event where EventID = #EventID
select * from EventCategory where EventID = #EventID
select * from EventHours where EventID = #EventID";
using (var multiResult = connection.QueryMultiple(sql, new { EventID = id }))
{
result = multiResult.Read<Event>().FirstOrDefault();
if (result != null)
{
result.Categories = multiResult.Read<EventCategory>().ToList();
result.Hours = multiResult.Read<EventHours>().ToList();
}
}
}
finally
{
connection.Close();
}
return result;
}
}
Finally I have the following markup in the view.
#Html.DropDownListFor(m => m.CategoryIds,
ViewBag.AvailableCategories as MultiSelectList,
new { multiple = "multiple", #class = "chzn-container" })
Now, as I stated at first, it's displaying properly and listing all of the categories as expected. However, even though the CategoryIds property does list in fact two selected categories, it's not setting them (or showing them for that matter) as selected in the Chosen drop down on load.
I am forced to only further assume that if a user selected a value from the Chosen drop down that it would not bind properly on post either because it does not change the HTML when an item is selected.
So, my question is this, how do I properly two-way data bind to a Chosen drop down in MVC?
ListBoxFor is the helper you should use for multiselect lists
replacing
#Html.DropDownListFor(m => m.CategoryIds,
ViewBag.AvailableCategories as MultiSelectList,
new { multiple = "multiple", #class = "chzn-container" })
with
#Html.ListBoxFor(m => m.CategoryIds,
ViewBag.AvailableCategories as MultiSelectList,
new { multiple = "multiple", #class = "chzn-container" })
should do the trick

Categories