I have a school database, where there are entities such as Year
, Grade
, Major
, ...
I'm trying to create a list of years in the _Layout.cshtml
and when the user chooses a year from the list, all views must retrieve data based on the selected year.
So I need to first create the list and then pass the selected year to all views.
I tried using a viewModel
but it didn't work. Now I'm trying to make use of TempData in a way to keep the list of years and the selected year, but I keep receiving the following error.
System.NullReferenceException: Object reference not set to an instance of an object.
Here is my AdminController:
public async Task<IActionResult> Index()
{
var allYears = await _context.Years.ToListAsync();
List<SelectListItem> yearList = new List<SelectListItem>();
foreach (var item in allYears)
{
yearList.Add(new SelectListItem { Text = item.Name, Value = item.Id.ToString() });
}
TempData["YearList"] = yearList;
TempData["CurrentYear"] = allYears.FirstOrDefault().Id.ToString();
return View(TempData);
}
This is the list in the partial view in _Layout.cshtml
. This is where I get the error. TempData is null.:
<select class="form-control" asp-for="@TempData["CurrentYear"]">
@foreach (var item in (List<SelectListItem>)TempData["YearList"])
{
<option>@item.Text</option>
}
</select>
I have also added this to _viewStart.cshtml
.
TempData["CurrentYear"] = 1;
TempData["YearList"] = null;
I have also tried this, but the issue still remains. Is there any way I can achieve this using TempData? Or Is there a better way?
Edit1: I removed the initialization in viewStart.cshtml
. But still I get the null exception error when navigating to another view.
Edit2: I used Session
instead of TempData
. Also I moved the dropdownlist to a separate view because I had a problem with adding a list to the session. But then RahulSharma
sent a tutorial in the comment section which is very helpful.
Thank you everyone.
Here is the prototype for your scenario
Controller
:
[HttpGet]
public async Task<IActionResult> Index()
{
TempData["YearList"] = new List<SelectListItem> { new ("2021", "2021"), new ("2022", "2022"), new ("2023", "2023") };
return View();
}
[HttpPost]
public async Task<IActionResult> Index(int year)
{
TempData["CurrentYear"] = year;
return RedirectToAction(nameof(Index));
}
View
:
<form method="post">
<select name="year">
@foreach (var year in (List<SelectListItem>)TempData["YearList"])
{
<option value="@year.Value">@year.Text</option>
}
</select>
<input type="submit" value="Send"/>
</form>
<h3>Selected year: @TempData["CurrentYear"]</h3>
Explanation:
[HttpGet]Index
action method renders years, no selected year on this stepTempData
and display select
control[HttpPost]Index
accept year argument (name matches name
attribute of select control). Put the selection into TempData
[HttpGet]Index
Points to consider: