我正在关注这个关于分页的教程。一切正常,但如果我从我的旧代码中添加一些排序和过滤,它就不起作用。错误说
NullReferenceException:对象引用未设置到对象的实例。
这是我的控制器
public async Task<IActionResult> Index()
{
return View(await GetStudentList(1));
}
[HttpPost]
public async Task<IActionResult> Index(int currentPageIndex)
{
return View(await GetStudentList(currentPageIndex));
}
// GET: Students
public IActionResult IndexProses(string sortOrder, StudentVM model)
{
ViewData["CurrentSort"] = sortOrder;
ViewData["NameSortParm"] = sortOrder == "name" ? "name_desc" : "name";
ViewData["DateSortParm"] = sortOrder == "Date" ? "date_desc" : "Date";
ViewData["FirstSortParm"] = String.IsNullOrEmpty(sortOrder) ? "first_desc" : "";
ViewData["CurrentFilter"] = model.FirstMidName;
ViewData["CurrentFilter2"] = model.LastName;
ViewData["CurrentFilter3"] = model.EnrollmentDateFrom;
ViewData["CurrentFilter3"] = model.EnrollmentDateUntil;
var students = from s in _context.Students
select s;
// sorting //
students = sortOrder switch
{
"name" => students.OrderBy(s => s.LastName),// asc last name
"name_desc" => students.OrderByDescending(s => s.LastName),//desc last name
"first_desc" => students.OrderByDescending(s => s.FirstMidName),// desc first name
"Date" => students.OrderBy(s => s.EnrollmentDate),// asc date
"date_desc" => students.OrderByDescending(s => s.EnrollmentDate),// desc date
_ => students.OrderBy(s => s.FirstMidName),// asc first name
};
// filtering
if (model.EnrollmentDateFrom != null && model.EnrollmentDateUntil != null)
{
students = students.Where(s => s.EnrollmentDate >= model.EnrollmentDateFrom && s.EnrollmentDate <= model.EnrollmentDateUntil);
}
if (!String.IsNullOrEmpty(model.LastName))
{
students = students.Where(s => s.LastName.Contains(model.LastName));
}
if (!String.IsNullOrEmpty(model.FirstMidName))
{
students = students.Where(s => s.FirstMidName.Contains(model.FirstMidName));
}
return View("Index", model);
}
private async Task<StudentVM> GetStudentList(int currentPage)
{
int maxRowsPerPage = 5;
StudentVM model = new StudentVM();
model.StundentList = await (from s in _context.Students select s)
.Skip((currentPage - 1) * maxRowsPerPage)
.Take(maxRowsPerPage).ToListAsync();
double pageCount = (double)((decimal)_context.Students.Count() / Convert.ToDecimal(maxRowsPerPage));
model.pageCount = (int)Math.Ceiling(pageCount);
model.currentPageIndex = currentPage;
return model;
}
我的假设是因为过滤排序是用Get方法,而分页是用Post方法。但我不知道如何修复它:(,这是。Index.cshtml 文件:
@model ContosoUniversity.Models.SchoolViewModels.StudentVM
@{
ViewData["Title"] = "Students";
//List<Student> students = ViewBag.students;
}
<style>
table{
margin-top: 20px;
}
.table a{
text-decoration: none;
}
/*.opsi a:hover{
text-decoration: underline;
}*/
h2{
margin-bottom: 20px;
}
.tbl{
display: flex;
gap: 1rem;
}
.box{
display: flex;
gap: 1rem;
margin-bottom: 10px;
}
</style>
<h2>Contoso University - Students</h2>
<form asp-action="IndexProses" asp-antiforgery="false" method="get">
<div class="form-actions no-color">
<h4>Search By</h4>
<div class="box">
<div class="search">
<label asp-for="FirstMidName"></label>
<input name="FirstMidName" type="text" value="@ViewData["CurrentFilter"]"/>
<br />
<span asp-validation-for="FirstMidName" class="text-danger"></span>
</div>
<div class="search">
<label asp-for="LastName"></label>
<input name="LastName" type="text" value="@ViewData["CurrentFilter2"]"/>
<br />
<span asp-validation-for="LastName" class="text-danger"></span>
</div>
<div class="search">
<label asp-for="EnrollmentDateFrom"></label>
<input name="EnrollmentDateFrom" type="date" value="@ViewData["CurrentFilter3"]"/>
<br />
<span asp-validation-for="EnrollmentDateFrom" class="text-danger"></span>
</div>
<div class="search">
<label asp-for="EnrollmentDateUntil"></label>
<input name="EnrollmentDateUntil" type="date" value="@ViewData["CurrentFilter4"]"/>
<br />
<span asp-validation-for="EnrollmentDateUntil" class="text-danger"></span>
</div>
<input type="submit" value="Search" class="btn btn-primary" />
</div>
</div>
</form>
<div class="tbl">
<a asp-action="Create" class="btn btn-primary">Create New [+]</a>
<a asp-action="Index" class="btn btn-info text-white">Back to List</a>
</div>
<form asp-action="Index" asp-controller="Students" method="post">
<table class="table table-hover">
<thead>
<tr class="table-light">
<th class="table-light">
@Html.ActionLink("First Name", "IndexProses", new { sortOrder = ViewBag.FirstSortParm, FirstMidName = Model.FirstMidName, LastName = Model.LastName, EnrollmentDateFrom = Model.EnrollmentDateFrom, EnrollmentDateUntil = Model.EnrollmentDateUntil })
</th>
<th>
@Html.ActionLink("Last Name", "IndexProses", new { sortOrder = ViewBag.NameSortParm, FirstMidName = Model.FirstMidName, LastName = Model.LastName, EnrollmentDateFrom = Model.EnrollmentDateFrom, EnrollmentDateUntil = Model.EnrollmentDateUntil })
</th>
<th>
@Html.ActionLink("Enrollment Date", "IndexProses", new { sortOrder = ViewBag.DateSortParm, FirstMidName = Model.FirstMidName, LastName = Model.LastName, EnrollmentDateFrom = Model.EnrollmentDateFrom, EnrollmentDateUntil = Model.EnrollmentDateUntil })
</th>
<th>Opsi</th>
</tr>
</thead>
<tbody class="opsi">
@foreach (var item in Model.StundentList)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a class="btn btn-warning text-white" asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a class="btn btn-info text-white" asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a class="btn btn-danger" asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
<ul class="pagination">
@for(int i=1; i<=Model.pageCount; i++)
{
<li class="page-item">
@if(i != Model.currentPageIndex)
{
<a class="page-link" href="javascript: PagerClick(@i);">@i</a>
}
else
{
<a class="page-link">@i</a>
}
</li>
}
</ul>
<input type="hidden" id="hfCurrentPageIndex" name="currentPageIndex"/>
</form>
<script type="text/javascript">
function PagerClick(index)
{
document.getElementById("hfCurrentPageIndex").value=index;
document.forms[0].submit();
}
</script>
这是 ViewModel
public class StudentVM : IValidatableObject
{
public int currentPageIndex { get; set; }
public int pageCount { get; set; }
public List<Student> StundentList { get; set; }
[Display(Name = "Last Name :")]
public string LastName { get; set; }
[Display(Name = "First Name :")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Date From :")]
public DateTime? EnrollmentDateFrom { get; set; } // ? (NULLABLE)
[DataType(DataType.Date)]
[Display(Name = "Until :")]
public DateTime? EnrollmentDateUntil { get; set; } // ? (NULLABLE)
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (FirstMidName == null)
{
yield return new ValidationResult("input first name!", new[] { "FirstMidName" });
//Memberi validation jika sebuah kolom pencarian tidak diisi!
}
if (LastName == null)
{
yield return new ValidationResult("input last name!", new[] { "LastName" });
//Memberi validation jika sebuah kolom pencarian tidak diisi!
}
if (EnrollmentDateFrom == null)
{
yield return new ValidationResult("input date from!", new[] { "EnrollmentDateFrom" });
//Memberi validation ke variable yang dituju!
}
if (EnrollmentDateUntil == null)
{
yield return new ValidationResult("input date until!", new[] { "EnrollmentDateUntil" });
//Memberi validation ke variable yang dituju!
}
}
}
对于过滤和排序教程,我正在关注this教程
需要实例化model.StundentList,先填充:
public IActionResult IndexProses(string sortOrder, StudentVM model)
{
......
model.StundentList = new List<Student>();
foreach (var student in students)
{
model.StundentList.Add(student);
}
return View("Index", model);
}
另外,你的代码好像逻辑有问题,可能是你还没写完吧
我建议你使用本教程中的方法进行分页。
更新:
因为点击页码的时候提交了forms[0],所以没有调用Index的post方法
改变
document.forms[0].submit();
到
document.forms[1].submit();
这样就可以调用Index的post方法了
看来你的
Model.StudentList
是空的。在将空值插入循环之前检查空值是个好主意。