Hello,
I am having two issues with the Select tag helper in my project. In both the Edit and Create views the validation for the Select tag helper is not working. Also the view is not setting to the selected option, as it seems to be stripping it away when displaying the view. Each view has multiple select tag helpers, pulling data from multiple tables.
So here is my controller for both the Create and Edit.
private readonly LotroModel _db; public CharactersController(LotroModel db) { _db = db; } public IActionResult Create() { var serverList = _db.Database.SqlQuery<ServersNamesListViewModel>("SELECT Server_ID AS ServerID, Server_Name AS ServerName FROM dbo.Server").ToList(); var professionList = _db.Database.SqlQuery<ProfessionNamesListViewModel>("SELECT Profession_ID AS ProfessionID, Profession_Name AS ProfessionName FROM dbo.Profession").ToList(); var levelList = _db.Database.SqlQuery<LevelNumbersListViewModel>("SELECT Level_ID AS LevelID, Level_Number AS LevelNumber FROM dbo.Level").ToList(); var classList = _db.Database.SqlQuery<ClassNamesListViewModel>("SELECT Class_ID AS ClassID, Class_Name AS ClassName FROM dbo.Class").ToList(); var raceList = _db.Database.SqlQuery<RaceNamesListViewModel>("SELECT Race_ID AS RaceID, Race_Name AS RaceName FROM dbo.Race").ToList(); var sList = new List<SelectListItem>(); var pList = new List<SelectListItem>(); var lList = new List<SelectListItem>(); var cList = new List<SelectListItem>(); var rList = new List<SelectListItem>(); foreach( ServersNamesListViewModel sn in serverList ) { sList.Add(new SelectListItem { Text = sn.ServerName, Value = sn.ServerID.ToString() }); } foreach( ProfessionNamesListViewModel pn in professionList ) { pList.Add(new SelectListItem { Text = pn.ProfessionName, Value = pn.ProfessionID.ToString() }); } foreach( LevelNumbersListViewModel ln in levelList ) { lList.Add(new SelectListItem { Text = ln.LevelNumber.ToString(), Value = ln.LevelID.ToString() }); } foreach( ClassNamesListViewModel cn in classList ) { cList.Add(new SelectListItem { Text = cn.ClassName, Value = cn.ClassID.ToString() }); } foreach( RaceNamesListViewModel rn in raceList) { rList.Add(new SelectListItem { Text = rn.RaceName, Value = rn.RaceID.ToString() }); } var character = new CharacterViewModel() { ServersList = sList, ProfessionList = pList, LevelList = lList, ClassList = cList, RaceList = rList }; return View(character); } // POST: Characters/Create // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create( CharacterViewModel returnedView, Character character) { if (ModelState.IsValid) { character.Char_First_Name = returnedView.Char_First_Name; character.Char_Last_Name = returnedView.Char_Last_Name; character.Char_Gender = returnedView.Char_Gender; character.ServerServer_ID = Convert.ToInt32(returnedView.ServersList.Select(x => x.Value)); character.Profession_Profession_ID = Convert.ToInt32(returnedView.ProfessionList.Select(x => x.Value)); character.Level_Level_ID = Convert.ToInt32(returnedView.LevelList.Select(x => x.Value)); character.Class_Class_ID = Convert.ToInt32(returnedView.ClassList.Select(x => x.Value)); character.Race_Race_ID = Convert.ToInt32(returnedView.RaceList.Select(x => x.Value)); _db.Characters.Add(character); await _db.SaveChangesAsync(); return RedirectToAction("Menu", "Menu"); } //This is not returning the dropdowns, need the returnView values as selected. return View(returnedView); } public async Task<IActionResult> Edit(int? id) { if(id == null) { return BadRequest(); } Character character = await _db.Characters.FindAsync(id); if(character == null) { return NotFound(); } var serverList = _db.Database.SqlQuery<ServersNamesListViewModel>(sql: "SELECT Server_ID AS ServerID, Server_Name AS ServerName, CAST( CASE WHEN Server_ID IN(SELECT ServerServer_ID FROM Character WHERE Char_ID = @p0) THEN 1 ELSE 0 END AS Bit) AS IsSelected FROM dbo.Server", parameters: new object[] { id }).ToList(); var professionList = _db.Database.SqlQuery<ProfessionNamesListViewModel>(sql: "SELECT Profession_ID AS ProfessionID, Profession_Name AS ProfessionName, CAST(CASE WHEN Profession_ID IN (SELECT Profession_Profession_ID FROM Character WHERE Char_ID = @p0) THEN 1 ELSE 0 END AS Bit) AS IsSelected FROM dbo.Profession", parameters: new object[] { id }).ToList(); var levelList = _db.Database.SqlQuery<LevelNumbersListViewModel>(sql: "SELECT Level_ID AS LevelID, Level_Number AS LevelNumber, CAST(CASE WHEN Level_ID IN (SELECT Level_Level_ID FROM Character WHERE Char_ID = @p0) THEN 1 ELSE 0 END AS Bit) AS IsSelected FROM dbo.Level", parameters: new object[] { id }).ToList(); var classList = _db.Database.SqlQuery<ClassNamesListViewModel>(sql: "SELECT Class_ID AS ClassID, Class_Name AS ClassName, CAST(CASE WHEN Class_ID IN (SELECT Class_Class_ID FROM Character WHERE Char_ID = @p0) THEN 1 ELSE 0 END AS Bit) AS IsSelected FROM dbo.Class", parameters: new object[] { id }).ToList(); var raceList = _db.Database.SqlQuery<RaceNamesListViewModel>(sql: "SELECT Race_ID AS RaceID, Race_Name AS RaceName, CAST(CASE WHEN Race_ID IN (SELECT Race_Race_ID FROM Character WHERE Char_ID = @p0) THEN 1 ELSE 0 END AS Bit) AS IsSelected FROM dbo.Race", parameters: new object[] { id }).ToList(); var sList = new List<SelectListItem>(); var pList = new List<SelectListItem>(); var lList = new List<SelectListItem>(); var cList = new List<SelectListItem>(); var rList = new List<SelectListItem>(); foreach (ServersNamesListViewModel sn in serverList) { sList.Add(new SelectListItem { Text = sn.ServerName, Value = sn.ServerID.ToString(), Selected = sn.IsSelected }); } foreach (ProfessionNamesListViewModel pn in professionList) { pList.Add(new SelectListItem { Text = pn.ProfessionName, Value = pn.ProfessionID.ToString(), Selected = pn.IsSelected }); } foreach (LevelNumbersListViewModel ln in levelList) { lList.Add(new SelectListItem { Text = ln.LevelNumber.ToString(), Value = ln.LevelID.ToString(), Selected = ln.IsSelected }); } foreach (ClassNamesListViewModel cn in classList) { cList.Add(new SelectListItem { Text = cn.ClassName, Value = cn.ClassID.ToString(), Selected = Selected = cn.IsSelected }); } foreach (RaceNamesListViewModel rn in raceList) { rList.Add(new SelectListItem { Text = rn.RaceName, Value = rn.RaceID.ToString(), Selected = Selected = rn.IsSelected }); } var eCharacter = new CharacterViewModel(); eCharacter.CharID = character.Char_ID; eCharacter.Char_First_Name = character.Char_First_Name; eCharacter.Char_Last_Name = character.Char_Last_Name; eCharacter.Char_Gender = character.Char_Gender; eCharacter.ServersList = sList; eCharacter.ProfessionList = pList; eCharacter.LevelList = lList; eCharacter.ClassList = cList; eCharacter.RaceList = rList; return View(eCharacter); }
Here is the View Model I am working with, plus a view model for the selectlistitem, all the selectlistitem view models are relatively the same, with just a change of data.
public class CharacterViewModel { [HiddenInput] public int CharID { get; set; } [Required] [StringLength(20)] [Display(Name = "First Name")] public string Char_First_Name { get; set; } [StringLength(20)] [Display(Name = "Last Name")] public string Char_Last_Name { get; set; } [Required] [StringLength(7)] [Display(Name = "Gender")] public string Char_Gender { get; set; } [Required] [Display(Name = "Server")] public List<SelectListItem> ServersList { get; set; } [Display(Name = "Profession")] public List<SelectListItem> ProfessionList { get; set; } [Required] [Display(Name = "Level")] public List<SelectListItem> LevelList { get; set; } [Required] [Display(Name = "Class")] public List<SelectListItem> ClassList { get; set; } [Required] [Display(Name = "Race")] public List<SelectListItem> RaceList { get; set; } }
public class ServersNamesListViewModel { [Key] public int ServerID { get; set; } [Required] [Display(Name = "Server Name")] public string ServerName { get; set; }
public bool IsSelected { get; set; } }
Lastly here are the two views, with the global portion of my javascript:
@* For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 *@ @model Lotro.WebAppMVC.Models.CharacterViewModels.CharacterViewModel @{ ViewBag.Title = "Create"; Layout = "~/Views/Shared/_CharAddLayout.cshtml"; }<h2 style="font-family:'Times New Roman', Times, serif; text-align:center; color:white">The Lord of the Rings Online Character Database</h2><form asp-controller="Characters" asp-action="Create" method="post"> <div class="form-horizontal"> <h4 style="font-family:'Times New Roman', Times, serif; text-align:center; color:white">Character Addition</h4> <hr /> <div asp-validation-summary="All" class="text-danger"></div> @*This is not doing validation correctly for the dropdowns. Might need a javascript to say if value = -- then not valid.*@ <div class="form-group"> <label asp-for="Char_First_Name" class="control-label col-md-2"></label> <div class="col-md-10"> <input asp-for="Char_First_Name" class="form-control" /> </div> </div> <div class="form-group"> <label asp-for="Char_Last_Name" class="control-label col-md-2"></label> <div class="col-md-10"> <input asp-for="Char_Last_Name" class="form-control" /> </div> </div> <div class="form-group"> <label asp-for="Char_Gender" class="control-label col-md-2"></label> <div class="col-md-10"> <input asp-for="Char_Gender" class="form-control" /> </div> </div> <div class="form-group"> <label asp-for="ServersList" class="control-label col-md-2"></label> <div class="col-md-10"> <select class="form-control single-select" asp-for="ServersList" asp-items="@Model.ServersList"> <option selected value="--">Select a Server</option> </select> </div> </div> <div class="form-group"> <label asp-for="ProfessionList" class="control-label col-md-2"></label> <div class="col-md-10"> <select class="form-control single-select" asp-for="ProfessionList" asp-items="@Model.ProfessionList"> <option selected value="--">Select a Profession</option> </select> </div> </div> <div class="form-group"> <label asp-for="LevelList" class="control-label col-md-2"></label> <div class="col-md-10"> <select class="form-control single-select" asp-for="LevelList" asp-items="@Model.LevelList"> <option selected value="--">Select a Level</option> </select> </div> </div> <div class="form-group"> <label asp-for="ClassList" class="control-label col-md-2"></label> <div class="col-md-10"> <select class="form-control single-select" asp-for="ClassList" asp-items="@Model.ClassList"> <option selected value="--">Select a Class</option> </select> </div> </div> <div class="form-group"> <label asp-for="RaceList" class="control-label col-md-2"></label> <div class="col-md-10"> <select class="form-control single-select" asp-for="RaceList" asp-items="@Model.RaceList"> <option selected value="--">Select a Race</option> </select> </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <div class="col-md-1"> <input type="submit" value="Create" class="btn btn-default" /> </div> <div class="col-md-1"></div> <div class="col-md-2"> <a asp-controller="Menu" , asp-action="Menu" , null, class="btn btn-danger col-md-push-3">Cancel</a> </div> </div> </div> </div></form>
@* For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 *@ @model Lotro.WebAppMVC.Models.CharacterViewModels.CharacterViewModel @{ ViewBag.Title = "Edit"; Layout = "~/Views/Shared/_CharEdLayout.cshtml"; }<h2 style="font-family:'Times New Roman', Times, serif; text-align:center; color:white">The Lord of the Rings Online Character Database</h2><form asp-controller="Characters" asp-action="Edit" method="post"> <div class="form-horizontal"> <h4 style="font-family:'Times New Roman', Times, serif; text-align:center; color:white">Edit Character</h4> <hr /> <div asp-validation-summary="All" class="text-danger"></div> <input asp-for="@Model.CharID" /> </div> <div class="form-group"> <label asp-for="Char_First_Name" class="control-label col-md-2"></label> <div class="col-md-10"> <input asp-for="Char_First_Name" class="form-control" /> </div> </div> <div class="form-group"> <label asp-for="Char_Last_Name" class="control-label col-md-2"></label> <div class="col-md-10"> <input asp-for="Char_Last_Name" class="form-control" /> </div> </div> <div class="form-group"> <label asp-for="Char_Gender" class="control-label col-md-2"></label> <div class="col-md-10"> <input asp-for="Char_Gender" class="form-control" /> </div> </div> <div class="form-group"> <label asp-for="ServersList" class="control-label col-md-2"></label> <div class="col-md-10"> <select class="form-control single-select" asp-for="ServersList" asp-items="@Model.ServersList"> <option value="--">Select a Server</option> </select> </div> </div> <div class="form-group"> <label asp-for="ProfessionList" class="control-label col-md-2"></label> <div class="col-md-10"> <select class="form-control single-select" asp-for="ProfessionList" asp-items="@Model.ProfessionList"> <option value="--">Select a Profession</option> </select> </div> </div> <div class="form-group"> <label asp-for="LevelList" class="control-label col-md-2"></label> <div class="col-md-10"> <select class="form-control single-select" asp-for="LevelList" asp-items="@Model.LevelList"> <option value="--">Select a Level</option> </select> </div> </div> <div class="form-group"> <label asp-for="ClassList" class="control-label col-md-2"></label> <div class="col-md-10"> <select class="form-control single-select" asp-for="ClassList" asp-items="@Model.ClassList"> <option value="--">Select a Class</option> </select> </div> </div> <div class="form-group"> <label asp-for="RaceList" class="control-label col-md-2"></label> <div class="col-md-10"> <select class="form-control single-select" asp-for="RaceList" asp-items="@Model.RaceList"> <option value="--">Select a Race</option> </select> </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <div class="col-md-1"> <input type="submit" value="Create" class="btn btn-default" /> </div> <div class="col-md-1"></div> <div class="col-md-2"> <a asp-controller="Menu" , asp-action="EdChar" , null, class="btn btn-danger col-md-push-3">Cancel</a> </div> </div> </div></form>
$(function () { $(".single-select").removeAttr("multiple"); });
What I see in the development tools for the web browsers is essentially the same, no errors show in the console. I am getting 200 OKs in the network section, but in my DOM, I see:
<div class="col-md-10"> <select name="ServersList" class="form-control single-select" id="ServersList" data-val-required="The Server field is required." data-val="true"> <option value="--">Select a Server</option> <option value="1">Arkenstone</option><option value="2">Anduin (DE)</option><option value="3">Belegaer (DE-RP)</option><option value="4">Brandywine</option><option value="5">Bullroarer (Public Test Server)</option><option value="6">Crickhollow</option><option value="7">Dwarrowdelf</option><option value="8">Eldar</option><option value="9">Elendilmir (Oceanic)</option><option value="10">Estel (FR-RP)</option><option value="11">Evernight (UK)</option><option value="12">Firefoot</option><option value="13">Fornost (RU-RP)</option><option value="14">Gilrain (UK)</option><option value="15">Gladden</option><option value="16">Gwaihir (DE)</option><option value="17">Imladris</option><option value="18">Landroval (US-RP)</option><option value="19">Laurelin (UK-RP)</option><option value="20">Maiar (DE)</option><option value="21">Meneldor</option><option value="22">Mirkwood (RU)</option><option value="23">Nimrodel</option><option value="24">Morthond (DE)</option><option value="25">Palantir (Private Test Server)</option><option value="26">Riddermark</option><option value="27">Silverlode</option><option value="28">Sirannon (FR)</option><option value="29">Snowbourn (UK)</option><option value="30">Vanyar (DE)</option><option value="31">Vilya</option><option value="32">Windfola</option><option value="33">Withywindle (UK)</option></select> </div>
If I look at the output from Visual Studio while debugging this section I see this:
Disabled: false
Group: null
Selected: true
Text: Brandywine
Value: 4
All others in that listing return false on the selected. This is essentially the same for all the other lists. What I get on the View is the "Select a Server" showing. So how do I get this to display the selected value when displaying the page. And with the validation, it returns the Select a Server as valid, I would guess because this never shows that these dropdown lists are invalid. I could leave everything blank on the screen for the Create and I only get two validation errors, while I should be getting 6 errors.
Does anyone see what I am doing wrong?