I am trying to filter my records by month and year. The filtering for the month works fine, but the filter for the year doesn't.
For some reason if I try to change the year it always sets the value for my SelectedYear-Property to "01/01/0001", or if I set a default value for my SelectedYear-Property (e.g. DateTime.Today) and if I try to change it it always hops back to the default value.
Maybe you can help me I can't figure out where the problem is.
Probably has something to do with wrong ModelBinding?
Here is my code:
Index.cshtml.cs
public class IndexModel : PageModel
{
private readonly CMSContext _context;
private readonly ILogger<IndexModel> _logger;
public IndexModel(CMSContext context, ILogger<IndexModel> logger)
{
_context = context;
_logger = logger;
}
public IList<TimeManagementModel> TimeManagementModel { get; set; }
[BindProperty(SupportsGet = true)]
public DateTime SelectedMonth { get; set; } = DateTime.Today;
[BindProperty(SupportsGet = true)]
public DateTime SelectedYear { get; set; } = DateTime.Today;
public async Task OnGetAsync()
{
_logger.LogInformation("SelectedYear value: {SelectedYear}", SelectedYear);
TimeManagementModel = await _context.TimeManagerModel
.Where(x => x.Date.Month == SelectedMonth.Month && x.Date.Year == SelectedYear.Year)
.OrderByDescending(x => x.Date)
.ToListAsync();
CalculateDailyWorkedHours();
CalculateOvertime(7.7);
}
}
Index.cshtml
@page
@model TestRazor.Pages.TimeManager.IndexModel
@{
ViewData["Title"] = "TimeManager";
}
<h1>Time Manager</h1>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script type="text/javascript" src="/js/TimeManager.js"></script>
</head>
<body>
<p>
<a asp-page="Create" class="btn btn-success">Create New</a>
</p>
<form method="get">
<div style="display: flex">
<div style="margin-right: 10px;">
<label for="selectedMonth">Select Month:</label>
<select name="SelectedMonth" id="selectedMonth" class="form-control" onchange="this.form.submit()">
@{
var today = DateTime.Today;
var selectedMonthValue = Model.SelectedMonth.ToString("yyyy-MM");
var months = Enumerable.Range(1, 12).Select(i => new DateTime(today.Year, i, 1));
foreach (var month in months)
{
<option value="@month.ToString("yyyy-MM")" selected="@(selectedMonthValue == month.ToString("yyyy-MM"))">
@month.ToString("MMMM")
</option>
}
}
</select>
</div>
<div>
<label for="selectedYear">Select Year:</label>
<select name="SelectedYear" id="selectedYear" class="form-control" onchange="this.form.submit()">
@{
var currentYear = DateTime.Today.Year;
for (var year = currentYear - 5; year <= currentYear + 5; year++)
{
<option value="@year" selected="@(Model.SelectedYear.Year == year)">@year</option>
}
}
</select>
</div>
</div>
</form>
</body>
Your SelectedYear
in backend is type of Datetime
, but your frontend year value is an int/string type which cannot be converted to Datetime by default.
One way is to change your backend type to int/string.
[BindProperty(SupportsGet = true)]
public int SelectedYear { get; set; }
And
<option value="@year" selected="@(Model.SelectedYear == year)">@year</option>
Another way is to set the value with Datetime
in frontend:
<option value="@(new DateTime(year,1,1).ToString("yyyy-MM"))" selected="@(Model.SelectedYear.Year == year)">@year</option>