MVC 4.6 Binding a drop down from dbContext - c#

I have an mvc empty project where I'm trying to pull questions from the database based on what a user select from a title drop down (The values for the dropdown also come from the database).
I have the drop down working with hard coded values so far. How can I pull the titles from the database and how can I pull the questions associated with the title selected.
The auto generated model I have looks like this
namespace Demo1.Models{
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Web.Mvc;
public partial class Title
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Title()
{
TitlesQuestions = new HashSet<TitlesQuestion>();
}
public int TitleId { get; set; }
[Column("Title")]
[Required]
[StringLength(20)]
public string Title1 { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<TitlesQuestion> TitlesQuestions { get; set; }
public SelectList TitleList { get; set; }
}
My ViewModel
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace Demo1.ViewModels.Titles
{
public class TitlesViewModel
{
public int TitleId { get; set; }
[Required]
[Display(Name = "Title")]
public string Title { get; set; }
public IEnumerable<SelectListItem> Titles { get; set; }
}
}
My Controller
using Demo1.Models;
using Demo1.ViewModels.Titles;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
namespace Demo1.Controllers
{
public class TitlesController : Controller
{
private EmployeeContext db = new EmployeeContext();
public IEnumerable<Title> GetTitleList()
{
var result = db.Titles.ToList();
return result;
}
// GET: Titles
public ActionResult Index()
{
var titles = GetAllTitles();
var model = new TitlesViewModel();
model.Titles = GetSelectListItems(titles);
return View(model);
}
private IEnumerable<string> GetAllTitles()
{
return new List<string>
{
"CEO",
"Project Manager",
"Technical Lead",
"Software Developer",
};
}
private IEnumerable<SelectListItem> GetSelectListItems(IEnumerable<string> elements)
{
var selectList = new List<SelectListItem>();
foreach (var element in elements)
{
selectList.Add(new SelectListItem
{
Value = element,
Text = element
});
}
return selectList;
}
}
}
My View
#model Demo1.ViewModels.Titles.TitlesViewModel
#{
ViewBag.Title = "Index";
}
<h2>Questions by Title Demo</h2>
<form asp-controller="Titles" asp-action="Index" method="post" class="form-horizontal" role="form">
<label asp-for="Title" class="col-md-2 control-label"></label>
<div>
#Html.DropDownListFor(m => m.Title, // 1. Store selected value in Model.Roles when page is rendered after postback,take selected value from Model.State.
Model.Titles, // 2. Take list of values from Model.Titles
"- Please select your title -", // 3. Text for the first 'default' option
new { #class = "form-control" }) #*// 4. A class name to assign to <select> tag*#
</div>
</form>

I'm using entity framework
private EmployeeContext db = new EmployeeContext();
I have a table named Titles
Here's my new ActionResult Index()
public ActionResult Index()
{
var model = new TitlesViewModel();
var titles = GetSelectListItems();
model.Titles = titles;
return View(model);
}
public IEnumerable<SelectListItem> GetSelectListItems()
{
foreach (var title in db.Titles)
{
yield return new SelectListItem
{
Value = title.TitleId.ToString(),
Text = title.Title1
};
}
}
When I try to run my project I get the following error
The class 'System.Web.Mvc.SelectList' has no parameterless constructor. I'm new to mvc so I'm not sure how to fix it. This seems like it should be a simple task I'm trying to bind data from the titles table to a drop down then once a title is selected I want the relevant questions from the database to show.

I think this is more of a question that involves on how to query a database. Overall this question needs alittle more context (what database is being used). Depending on what you're using there are many ways to query a database. My favorite for SQL is using ADO.NET Entity Data Model. This is a database first approach. It creates a .edmx that creates all the models from the tables you select when setting it up.
After Setup:
Access data entities
MyAccountEntities users = new MyAccountEntities();
Access tables(use LINQ to change DbSet<UserAccount> to List<UserAccount>) ;)
users.UserAccounts.ToList();
Use LINQ to query your table/list. (returns a list of users named bob)
string username = "bob";
users.UserAccounts.Where(u => u.username == username).ToList();
UPDATE!!!!
Thank you for narrowing your problem down. The problem is pretty straight-forward. You have no constructor that takes parameters for your SelectListItem model. Go to where the model is defined then create a constructor with the parameters you wish to pass it.
Hope this Helps. Cheers :)

Related

Select tag helper from database ASP.NET Core 3.1

Ok, I'm trying to do a proper dropdown in Core 3.1. In this example https://learn.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-select-tag-helper
Model has a new list with hardcoded values
public string Country { get; set; }
public List<SelectListItem> Countries { get; } = new List<SelectListItem>
{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
};
I looked for examples where the list is coming from the database but they are very inconsistent. The only way I was able to do the dropdown list is with the ViewBag which is not advised.
I have two models. 1.
public partial class Glossary
{
public int UniqueId { get; set; }
public int Category { get; set; }
public string DisplayText { get; set; }
}
which is my view model
public partial class AdminUser
{
[Key]
public int Id { get; set; }
public string UserName { get; set; }
public string UserLocation { get; set; }
public string UserStatus { get; set; }
//public IEnumerable<Glossary> Glossary { get; set; } //I used this for ViewBag
public List<SelectListItem> UserLocations { get; } = new List<SelectListItem>
{
according to the example my query should go here
};
}
Here is my controller:
public IActionResult Create()
{
// This is the ViewBag that worked with HTML helpers, but I'm trying to use tag-helpers.
/*IEnumerable<SelectListItem> LocationsList = _context.Glossary.Where(x => x.Category == 1).Select(x => new SelectListItem
{
Value = x.UniqueId.ToString(),
Text = x.DisplayText
});
ViewBag.LocationsList = LocationsList;
*/
return View();
}
All examples that found were hardcoded lists and nothing with getting it from the database. What is the proper way to get the data from the Glossary table through the view model with ViewBag? Any pointers are appreciated.
ALSO:
When using this example: Select Tag Helper in ASP.NET Core MVC
When I used
public SelectList Employees { set; get; }
I got error: InvalidOperationException: The entity type 'SelectListGroup' requires a primary key to be defined. If you intended to use a keyless entity type call 'HasNoKey()'.
Both of my tables have PK and adding [Key] to Glossary model didn't fix it.
If you'd like to retrieve data from db and populate a dropdown with retrieved data through a view model (or ViewBag), you can refer to following code snippet.
In AdminUser view model class, include these properties
public string Selected_Glossary { get; set; }
public List<SelectListItem> Glossary_List { get; set; }
In controller
public IActionResult Create(AdminUser model)
{
var adminuser_model = new AdminUser
{
UserName="test"
//for other properties
};
//retrieve data from Glossary table
var items = _context.Glossary.Where(x => x.Category == 1).Select(x => new SelectListItem
{
Value = x.UniqueId.ToString(),
Text = x.DisplayText
}).ToList();
//pass dropdown items through a view model
adminuser_model.Glossary_List = items;
////pass dropdown items through ViewBag
//ViewBag.Glossary_List = items;
return View(adminuser_model);
}
In view page
#model AdminUser
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<form asp-controller="Home" asp-action="Create" method="post">
<select asp-for="Selected_Glossary" asp-items="Model.Glossary_List"></select>
#*populate it through ViewBag*#
#*<select asp-for="Selected_Glossary" asp-items="ViewBag.Glossary_List"></select>*#
<input type="submit" value="Submit" />
</form>
Test Result

MVC Dropdown option displayed as 'null' in debug mode

Afternoon Folks,
Im new to MVC 5 and C# and have a simple form with several fields and a dropdown box. I have used the CRUD method for entity framework and can successfully view and create new records in the system.
The only issue that I have is I have a 'Title' dropdown that links to the entity framework and populates these titles into a list. when I load my web page I can now see the titles available in the dropdown list, but when submitting the form, all the values but the 'Title' field are submitted into the database.
When I debug my program, this field regardless of what I select displays null.
I have followed the following tutorial to get this wo work and looked around the net but im struggeling to find a solution.
Link to tutorial
I have two tables in my model, one named 'Title' and the other named 'Client Record'.
As I have used the database first approach and not code first I have combined these two database models into one:
namespace EDT_Test.Models.ViewModels
{
public partial class Marie_Testing
{
[Display(Name = "Client Ref:")]
public int id { get; set; }
[Display(Name = "Created By:")]
public string CreatedBy { get; set; }
public List<Title> allTitles { get; set; }
[Required]
[Display(Name = "Surname:")]
public string Surname { get; set; }
[Display(Name = "Additional Surname:")]
public string Surname2 { get; set; }
[Required]
[Display(Name = "Forename:")]
public string Forename1 { get; set; }
[Display(Name = "Additional Forename:")]
public string Forename2 { get; set; }
The generated Entity Framework model looks like this:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace EDT_Test.Models
{
using System;
using System.Collections.Generic;
public partial class ClientRecord
{
public int id { get; set; }
public string CreatedBy { get; set; }
public string Title { get; set; }
public string Surname { get; set; }
public string Surname2 { get; set; }
public string Forename1 { get; set; }
public string Forename2 { get; set; }
}
}
The only difference for the Title field between the auto created model and Marie_Testing model is I have changed the Title field from a string to a list item.
My Create.cshtml holds a div for the Title dropdown that looks like this (This links to my model named Marie_Testing and not the auto generated ones created by the Entity Framework:
<div class="form-group">
#Html.LabelFor(model => model.allTitles, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<select id="titleid" name="titlename" class="form-control">
#foreach (var item in Model.allTitles)
{
<option value="#item.id">#item.Title1</option>
}
</select>
</div>
</div>
My code for the ClientRecordsController is:
// GET: ClientRecords/Create
public ActionResult Create()
{
////set the defaults (dropdown) of the page for the ceaton of a new record.
Marie_Testing vmPopulateData = new Marie_Testing();
List<Title> titles = (from t in db.Titles select t).ToList();
//List<Title> titles = Title.Select(t => new{t.id, t.Title}.ToString.ToList());
vmPopulateData.allTitles = titles;
return View(vmPopulateData);
}
// POST: ClientRecords/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id,CreatedBy,Title,Surname,Surname2,Forename1,Forename2")] ClientRecord clientRecord)
{
if (ModelState.IsValid)
{
db.ClientRecords.Add(clientRecord);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(clientRecord);
}
Any help is much appreciated as I don't understand how can see the dropdown list in the web page but cannot seem to grab the selected value and post this to the database.
Regards
Betty B
Why not try the #Html.DropDownListFor?
Instead of this:
<select id="titleid" name="titlename" class="form-control">
#foreach (var item in Model.allTitles)
{
<option value="#item.id">#item.Title1</option>
}
</select>
try:
#Html.DropDownListFor(x => x.PropertyToBindTo, new SelectList(Model.allTitles, "id", "Title1"), new { #class = "form-control", id = "Title", name = "Title" })
Where x.PropertyToBindTo is whatever value that you need to get from that select list. Try it out... you may have to play with it a little in order to really understand how you need to work it.
You need to have a string field to hold the value of the selected from the dropdown so your view would change from
<select id="titleid" name="titlename" class="form-control">
to
<select id="Title" name="Title" class="form-control">
And you will also have a Title property on your view model like this
public string Title{get;set;}
You need to have a read on how MVC binds forms to models to get an understanding of why this happens.
Hope this helps..
well I prefer to use this
C#
List<Titles> oTitlesList = TitlesService.getTitles();
ViewBag.DropDownListBag = new SelectList(oTitlesList , "Id", "Name");
Razor
#Html.DropDownListFor(model => model.yourModelAtt, #ViewBag.DropDownListBag as SelectList, "Select.....", new { #class = "form-control" })

How to populate a Select taghelper in Razor using data from a SQL database table

I'm using ASP.NET Core 1.0 and EF Core 1.0 and have the following code-first class in my SQL database.
namespace GigHub.Models
{
public class Genre
{
public byte Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
}
}
I also have the following ViewModel class I use in a Razor view form:
namespace GigHub.ViewModels
{
public class GigFormViewModel
{
public string Venue { get; set; }
public string Date { get; set; }
public string Time { get; set; }
public List<Genre> Genres { get; set; }
}
}
I also have this controller:
using GigHub.Data;
using GigHub.ViewModels;
using Microsoft.AspNetCore.Mvc;
namespace GigHub.Controllers
{
public class GigsController : Controller
{
private readonly ApplicationDbContext _context;
public GigsController(ApplicationDbContext context)
{
_context = context;
}
public IActionResult Create()
{
var vm = new GigFormViewModel();
// Need to get my Genre list from the DbSet<Genre> in my database context injected above
// into the GigFormViewModel for the Select taghelper to consume
return View(vm);
}
}
}
I have my Razor view set up to use the ViewModel fine but I'm unsure how the Select taghelper code below should be set up to access the Genre property.
<div class="form-group">
<label asp-for="????" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select asp-for="????" asp-items="????" class="form-control"></select>
<span asp-validation-for="????" class="text-danger" />
</div>
</div>
I'm basically having trouble grokking how to get my list of genres from my database into the ViewModel property in a form that the Select taghelper asp-items= can consume. The many trial & error contortions I've gone through generally result in conversion issues going from generic List<> type to MVCs SelectListItem type. I suspect my ViewModel Genre class needs adjusting but my research thus far has only resulted in articles covering previous versions of ASP.NET and Entity Framework and I struggle to map them to ASP.NET core 1.0 RC2 and EF Core 1.0.
You can use asp-for to specify the model property name for the select element and asp-items to specify the option elements.
<select asp-for="SomeFiles" asp-items="Model.SomeOptions"></select>
You can also use ViewBag.SomeOptions if you don't want to add the SomeOptions filed to the mode.
For more information take a look at The Select Tag Helper documentation.
Example
View
<select asp-for="Country" asp-items="Model.Countries"></select>
Model
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace FormsTagHelper.ViewModels
{
public class CountryViewModel
{
public string Country { get; set; }
public List<SelectListItem> Countries { get; set; }
}
}
Controller
The Index method initializes the CountryViewModel, sets the selected country and list of countries and passes the model to the Index view.
public IActionResult Index()
{
var model = new CountryViewModel();
model.Country = "CA";
model.Countries = db.Countries
.Select(x => new SelectListItem { Value = x.Id, Text = x.Name })
.ToList();
return View(model);
}

Create DropDownListFor using strings from a List<string>

I feel this should be simple but haven't found a guide on here that explains the use of dropdownlistfor in MVC.
I have a simple List of Names in a method in a class Users:
public List<string> getUsersFullNames()
{
return (from da in db.Dat_Account
join ra in db.Ref_Account on da.AccountID equals ra.AccountID
select ra.FirstName + " " + ra.Surname).ToList();
}
I want to display each of these names in a dropdownlist so that a name can be selected.
I tried to get this working but have had no success.
My controller:
[Authorize]
public ActionResult ManageUserAccounts()
{
ViewBag.UserList = oUsers.getUsersFullNames();
return View();
}
My Model:
public class ManageUserAccountsViewModel
{
[Display(Name = "Users")]
public List<SelectListItem> UserList { get; set; }
}
My View:
Html.DropDownListFor(model => model.UserList, new SelectList(oUsers.getUsersFullNames(), "Select User"));
I'm quite new to asp.net MVC as I have always used webforms in the past. Has anyone any idea if this is possible or a way to display this?
Thanks,
I would recommend using the model directly in the view, instead of the ViewBag. Update your action to include a model reference:
public ActionResult ManageUserAccounts()
{
var model = new ManageUserAccountsViewModel();
model.UserList = oUsers.getUsersFullNames();
return View(model);
}
Your model should be updated to include a selected User property:
public class ManageUserAccountsViewModel
{
public string User { get; set; }
[Display(Name = "Users")]
public List<string> UserList { get; set; }
}
Your view should be binding to the model:
#model ManageUserAccountsViewModel
#Html.DropDownListFor(m => m.User, new SelectList(Model.UserList), "Select User")

Can't convert data retrieved from datasets to a model type ienumerables

I always get the error-- cannot convert to 'MvcMusicStore.Models.MusicStore.GenreDataTable' to 'System.Collections.Generic.IEnumerable'
I am pasting my code below
the controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcMusicStore.Models;
namespace MvcMusicStore.Controllers
{
public class StoreController : Controller
{
// GET: /Store/
public ActionResult Index()
{
MvcMusicStore.Models.MusicStoreTableAdapters.GenreTableAdapter ta= new Models.MusicStoreTableAdapters.GenreTableAdapter();
var genres = ta.GetData().AsEnumerable();
return View(genres);
}
my model:
namespace MvcMusicStore.Models
{
public partial class Genre
{
public int GenreId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<Album> Albums { get; set; }
}
}
and at last the view:
#model IEnumerable<MvcMusicStore.Models.Genre>
#{
ViewBag.Title = "Index";
}
<h3>Browse Genres</h3>
<p>
Select from #Model.Count()
genres:
</p>
<ul>
#foreach (var genre in Model)
{
<li>#Html.ActionLink(genre.Name,
"Browse", new { genre = genre.Name })</li>
}
</ul>
It looks like ta.GetData() is not returning an object that can be cast into an IEnumerable<Genre>. Based on the error message it seems that ta.GetData() is returning a GenreDataTable object. If that is correct, I see a couple of things:
In the Razor view, the model is looking for a IEnumerable of Genre objects not a GenreDataTable object.
If your GenreDataTable object is already a collection, then have that as the return model instead of the IEnumerable.
If GenreDataTable is not a collection of Genre objects, then you've got to either update the required model in the Razor view, or update the controller code to create the required type to match the model.

Categories