I’ve done basic sorts before and not had an issue, but this one has me stumped as to what I am doing wrong. All it returns is a blank page.
Details.cs (showing the sort code)
using RabiesClinics.Data;
using RabiesClinics.Model;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
namespace RabiesClinics.Pages.Pets;
[BindProperties]
public class DetailsModel : PageModel
{
private readonly ApplicationDbContext _db;
public Pet Pet { get; set; }
public Vaccine Vaccine { get; set; }
public IEnumerable<Vaccine> VaxList { get; set; }
public string VaxDateSort { get; set; }
public DetailsModel(ApplicationDbContext db)
{
_db = db;
}
public async Task<IActionResult> OnGetAsync(int ownerid, string id, string sortOrder)
{
var ownerid1 = ownerid;
Pet = _db.Pet.Include(pet => pet.Vaccines).FirstOrDefault(pet => pet.PetId == id);
VaxDateSort = sortOrder == "VaxDate_Asc_Sort" ? "VaxDate_Desc_Sort" : "VaxDate_Asc_Sort";
IQueryable<Model.Vaccine> vaccine = from s in _db.Vaccine select s;
switch (sortOrder)
{
case "VaxDate_Asc_Sort":
vaccine = vaccine.OrderBy(s => s.DateVaccinated.ToString());
break;
case "VaxDate_Desc_Sort":
vaccine = vaccine.OrderByDescending(s => s.DateVaccinated.ToString());
break;
default:
vaccine = vaccine.OrderBy(s => s.DateVaccinated.ToString());
break;
}
Vaccine = await vaccine.ToListAsync();
if (Pet is null)
return new NotFoundResult();
else
return Page();
}
}
Pet Details view where the sort occurs (shortened for space):
@page
@using RabiesClinics.Model
@model RabiesClinics.Pages.Pets.DetailsModel
<form method="post">
<div class="border p-3 mt-4">
<div class="row pb-2">
<h2 class="text-primary pl-3">Pet Details <img src="~/Images/PawPrints.png" /></h2>
<hr />
</div>
<table class="table table-borderless" style="width:100%">
<tr>
<td style="width: 20%">
<div class="mb-3">
<label asp-for="Pet.OwnerId"></label>
<input asp-for="Pet.OwnerId" name="ownerid" disabled class="form-control" />
</div>
</td>
<td style="width: 20%">
<div class="mb-3">
<label asp-for="Pet.PetId"></label>
<input asp-for="Pet.PetId" name="id" disabled class="form-control" />
</div>
</td>
<td style="width: 20%">
<div class="mb-3">
<label asp-for="Pet.PetName"></label>
<input asp-for="Pet.PetName" type="text" disabled class="form-control"/>
</div>
</td>
<td style="width: 20%">
<div class="mb-3">
<label asp-for="Pet.LastVaxDate"></label>
<input asp-for="Pet.LastVaxDate" type="text" disabled class="form-control" />
</div>
</td>
<td style="width: 20%">
<div class="form-group, mb-3">
<label asp-for="Pet.Status"></label>
<br />
@foreach (var item1 in Html.GetEnumSelectList<Status>())
{
<input type="radio" disabled asp-for="Pet.Status" value="@item1.Text" />
@item1.Text
}
</div>
</td>
</tr>
</table>
<hr />
<h4>Vaccines</h4>
<br />
<table class="table table-bordered table-striped width:100%">
<thead>
<tr>
<th>
Tag No
</th>
<th>
<a asp-page="./Details" asp-route-sortOrder="@Model.VaxDateSort">Date Vaxxed</a>
</th>
<th>
Print Rabies Certificate
</th>
</tr>
</thead>
<tbody>
@for (var i = 0; i < Model.Pet.Vaccines.Count; i++)
{
<tr>
<td style="width: 10%">
<div class="mb-3">
<input asp-for="Pet.Vaccines[i].RabiesTagNo" type="text" readonly class="form-control-plaintext" />
</div>
</td>
<td style="width: 10%">
<div class="mb-3">
<input asp-for="Pet.Vaccines[i].DateVaccinated" type="date" readonly class="form-control-plaintext" />
</div>
</td>
<td width="10%">
<div class="w-75 btn-group" role="group">
<!--Line below is good.-->
<a asp-page="/RabiesCertificates/Details" class="btn btn-primary mx-2" asp-route-id="@Model.Pet.PetId" asp-route-vaxdate="@Model.Pet.Vaccines[i].DateVaccinated">
<i class="bi bi-printer"></i>
</a>
</div>
</td>
</tr>
}
</table>
<div>
<a asp-page="/Owners/Details" asp-route-ownerid="ownerid1" asp-route-id="@Model.Pet.OwnerId" class="btn btn-primary" style="width: 250px;">Back to Owner Details</a>
</div>
</div>
</form>
@section Scripts{
<partial name="_ValidationScriptsPartial"/>
}
If someone could point out where I have gone astray, I would much appreciate it! I have learned a lot from this forum so far that I have been able to apply on multiple apps!
ADDED: Update based on suggestion
public async Task<IActionResult> OnGetAsync(int ownerid, string id, string sortOrder, DateTime vax)
{
var ownerid1 = ownerid;
Pet = _db.Pet.Include(pet => pet.Vaccines).FirstOrDefault(pet => pet.PetId == id);
VaxDateSort = sortOrder == "VaxDate_Asc_Sort" ? "VaxDate_Desc_Sort" : "VaxDate_Asc_Sort";
IQueryable<Model.Vaccine> vaccine = from s in _db.Vaccine select s;
switch (sortOrder)
{
case "VaxDate_Asc_Sort":
vaccine = vax.OrderBy(s => s.DateVaccinated);
break;
case "VaxDate_Desc_Sort":
vaccine = vax.OrderByDescending(s => s.DateVaccinated);
break;
default:
vaccine = vax.OrderBy(s => s.DateVaccinated);
break;
}
VaxList = await vax.ToListAsync();
2
Answers
Code should look like this
I’ll start off with a few QoL improvements.
You used 14 lines to describe sorting:
There’s something to be said for keeping it like this if you expect multiple sorting methods to be added in the future. However, the devil is in the details:
Why are you making the
VaxDateSort
the opposite ofsortOrder
? Why even have a seperate property if you don’t mutate it afterwards?Since
VaxDateSort
is implied to always have a value, you can add thedefault
switch statement to another case, like:Now, you already had some help with fixing some of your other mistakes, so putting it all together with your improved version and fixing the last mistakes you made (
vax
was the datetime parameter of your method, not the db list), this should let your code compile at least.I recommend taking a close look at the official MS documentation example of what you’re trying to do and cross-referencing https://learn.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-8.0&tabs=visual-studio