Good morning, I have a MVC view that was working fine in .Net Core 3.1. The view is essentially three sections. An input box for the name, a row of radio buttons, and field of checkboxes. This worked perfectly fine. I made no changes to my ViewModels, View, or Controller. The only change I made was on the project xml file, changing the TargetFramework from netcoreapp3.1 to net6.0. Now when I go to the view and make a change, whether the name or a radio button or a checkbox, I hit the submit button, I get validation returns that is essentially saying each Checkbox and Radio button must be checked. I put a breakpoint in the post controller right at ModelState.IsValid and it is not hitting the break point. Was there a breaking change I missed in the documentation? How do I make this work correctly?
Here is information from controller, views, and ViewModels. Again no changes to any of this, which worked in .Net Core 3.1.
Controller:
// GET: Factions/Edit/5
public async Task<IActionResult> Edit( int? id )
{
//If the FactionID is null then return the error, else get the databse information and display it
if ( id==null )
{
return BadRequest();
}
//get the information from the database for the Faction
FactionViewModel eFaction = await _dts.GetFactionViewModelByIdAsync(id.Value);
//If the database information does not exist, return not found
if ( eFaction==null )
{
return NotFound();
}
//Display the View
return View( eFaction );
}
// POST: Factions/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit( FactionViewModel returnedView )
{
//If the returnedView model state is valid, save the changes to the database
if ( ModelState.IsValid )
{
await _dts.UpdateFactionAsync(returnedView);
return RedirectToAction( "Index" );
}
//generate the view if something is wrong, use the current ID
var id = returnedView.FactionNames.FactionID;
FactionViewModel newView = await _dts.GetFactionViewModelByIdAsync(id);
//Use the information the user typed
newView.FactionNames = new FactionNamesListViewModel()
{
FactionID = returnedView.FactionNames.FactionID,
FactionName = returnedView.FactionNames.FactionName
};
//Place the selected Reputation Type in the View
newView.ReputationTypesID = returnedView.ReputationTypesID;
//Display the View
return View( newView );
}
View Models
FactionViewModel:
public FactionViewModel()
{
this.FactionNames = new FactionNamesListViewModel();
this.ReputationTypes = new List<ReputationTypeNamesListViewModel>();
this.ReputationLevels = new List<ReputationLevelNamesListViewModel>();
}
public FactionNamesListViewModel FactionNames { get; set; }
[Required]
[Display(Name = "Reputation Type to be associated with Faction")]
public int ReputationTypesID { get; set; }
public List<ReputationTypeNamesListViewModel> ReputationTypes { get; set; }
[Required]
[Display(Name = "Reputation Levels that apply to the Faction")]
public List<ReputationLevelNamesListViewModel> ReputationLevels { get; set; }
FactionsNamesListViewModel:
[HiddenInput]
public int FactionID { get; set; }
[Required]
[Display(Name = "Name")]
public string FactionName { get; set; }
public bool IsSelected { get; set; }
ReputationTypeNamesListViewModel:
public class ReputationTypeNamesListViewModel
{
public int ReputationTypeID { get; set; }
[Display(Name = "Reputation Type Name")]
public string ReputationTypeName { get; set; }
public bool IsSelected { get; set; }
}
ReputationLevelNamesListViewModel:
public class ReputationLevelNamesListViewModel
{
public int ReputationLevelID { get; set; }
public string ReputationLevelName { get; set; }
public bool IsChecked { get; set; }
}
Data Calls:
public async Task<FactionViewModel> GetFactionViewModelByIdAsync(int id)
{
FactionViewModel output = new()
{
FactionNames = await GetFactionNamesListViewModelsAsync(id),
ReputationTypes = await _repTypes.GetReputationTypesNamesListViewModelByIdAsync(id),
ReputationLevels = await _repLevels.GetReputationLevelNamesViewModelByIdAsync(id)
};
return output;
}
public async Task<FactionNamesListViewModel> GetFactionNamesListViewModelsAsync(int id)
{
return await _db.Set<FactionNamesListViewModel>().FromSqlRaw(sql: "SELECT Faction_ID AS FactionID, Faction_Name AS FactionName, CAST (1 AS bit) AS IsSelected FROM Faction WHERE Faction_ID = @p0", parameters: new object[] { id }).FirstOrDefaultAsync();
}
public async Task<List<ReputationTypeNamesListViewModel>> GetReputationTypesNamesListViewModelByIdAsync(int id)
{
List<ReputationTypeNamesListViewModel> output = await _db.Set<ReputationTypeNamesListViewModel>().FromSqlRaw(sql: "SELECT Reputation_Type_ID AS ReputationTypeID, Reputation_Type_Name AS ReputationTypeName, CAST (CASE WHEN Reputation_Type_ID IN (SELECT ReputationTypeReputation_Type_ID FROM Faction WHERE Faction_ID = @p0) THEN 1 ELSE 0 END AS bit) AS IsSelected FROM ReputationType WHERE ActiveRecord = 1", parameters: new object[] { id }).ToListAsync();
return output;
}
public async Task<List<ReputationLevelNamesListViewModel>> GetReputationLevelNamesViewModelByIdAsync(int id)
{
List<ReputationLevelNamesListViewModel> output = await _db.Set<ReputationLevelNamesListViewModel>().FromSqlRaw(sql: "GetRepLevelList @p0", parameters: new object[] { id }).ToListAsync();
return output;
}
View:
@{
ViewData[ "Title" ] = "Edit";
Layout = "~/Views/Shared/_GameDataLayout.cshtml";
}
@model Lotro.ViewModelClass.Dtl.Models.FactionViewModels.FactionViewModel
<h2>Edit</h2>
<form asp-controller="Factions" asp-action="Edit" method="post">
<div class="form-horizontal">
<h4>Factions</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group row">
<label asp-for="@Model.FactionNames.FactionName" class="control-label col-lg-2"></label>
<div class="col-lg-10">
<input type="hidden" asp-for="@Model.FactionNames.FactionID" />
<input asp-for="@Model.FactionNames.FactionName" class="form-control" />
</div>
</div>
<div class="form-group row">
<label asp-for="@Model.ReputationTypesID" class="control-label col-lg-12" style="text-align:center"></label>
<div class="col-lg-12 row">
@for ( var i = 0; i < @Model.ReputationTypes.Count; i++ )
{
<div class="col-lg-2">
<input type="hidden" asp-for="@Model.ReputationTypes[i].ReputationTypeID" />
<input type="radio" asp-for="@Model.ReputationTypesID" value="@Model.ReputationTypes[i].ReputationTypeID" checked="@Model.ReputationTypes[i].IsSelected" />
<b>@Html.DisplayFor( model => model.ReputationTypes[ i ].ReputationTypeName )</b>
</div>
}
</div>
</div>
<div class="form-group row">
<label asp-for="@Model.ReputationLevels" class="control-label col-lg-12" style="text-align:center"></label>
<div class="col-lg-12 row">
@{ int j = 0; }
@for ( var i = 0; i < Model.ReputationLevels.Count; i++ )
{
<input type="hidden" asp-for="@Model.ReputationLevels[i].ReputationLevelID" />
<div class="col-lg-1">
<input type="checkbox" asp-for="@Model.ReputationLevels[i].IsChecked" />
</div>
<div class="col-lg-2">
@Html.DisplayFor( model => model.ReputationLevels[ i ].ReputationLevelName )
</div>
j++;
if ( j == 4 )
{
<div class="col-lg-12"><br /></div>
j = 0;
}
else
{
continue;
}
}
</div>
</div>
<div class="form-group row">
<div class="col-lg-offset-2 col-lg-10">
<input type="submit" value="Save" class="btn btn-secondary" />
</div>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
</form>