我正在使用Visual Studio 2017并使用Entity Framework创建了一个标准的ASP.NET / MVC项目,最后包含了一个本地数据库。 我有课程"课程"和"类别"。一门课程可以有一个类别,一个类别可以在许多课程中。 (n:1关系)
我的模型适用于我的课程:
namespace project.Models
{
public class Course
{
public int ID { get; set; }
public int CategoryID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual CourseCategory CourseCategory { get; set; }
}
courseCategory.cs的模型是:
namespace project.Models
{
public class CourseCategory
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Course> Course { get; set; }
}
}
观点是:
@model IEnumerable<Models.Courses>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.ID)
</th>
<th>
@Html.DisplayNameFor(model => model.CategoryID)
</th>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Description)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.ID)
</td>
<td>
@Html.DisplayFor(modelItem => item.CategoryID)
</td>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Description)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a>
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
从这两个类派生,我自动创建了控制器和视图。我做&#34; add-migration -xx&#34;和&#34;更新数据库&#34;我的应用程序是可运行的。 我打开&#34; http://localhost/courses&#34;我有我的课程列表(包括课程的给定类别),可以添加,移动删除等... 如果我查看我的数据库/表,我可以看到正确的主键和外键。它有效......
但是现在,我希望增加过滤课程的可能性。我需要额外的一部分,我的类别列在其中,如果我点击其中一个类别,我想要一个新的结果列表,所有课程与点击的类别。
我如何实现它以及我必须修改代码的位置? 我试图修改CourseController.cs
// GET: Course
public async Task<IActionResult> Index()
{
return View(await _context.Course.ToListAsync());
}
我想我在这里需要一些思考,比如表中主键的比较?
答案 0 :(得分:1)
这就是你需要的
有多种方法可以做到这一点。这就是我将如何做到的。
我不想在我的UI层中混合ORM创建的实体类。所以我创建了一个特定于视图的视图模型
public class CourseListVm
{
public int? CategoryId { set;get;}
public List<SelectListItem> Categories { set;get;}
public IEnumerable<CourseVm> Courses { set;get;}
public CourseListVm()
{
this.Courses = new List<CourseVm>();
}
}
public class CourseVm
{
public int Id { set;get;}
public string Name { set;get;}
}
现在,在您的操作方法中,创建一个此对象,将可用类别从数据库加载到Categories
属性。我们将向action方法添加一个参数,并检查是否有选定catetory的值(来自ui),如果是,我们将在填充Courses
属性时进行过滤
public async Task<IActionResult> Index(int? categoryId)
{
var vm=new CourseListVm();
//Populate the catetory list so that we can use that in UI to build the dropdown
vm.Categories = _context.Categories
.Select(a => new SelectListItem() {Value = a.Id.ToString(),
Text = a.Name})
.ToList();
List<Course> courseList = new List<Course>();
if(categoryId==null)
{
courseList = await _context.Course.ToListAsync()
}
else
{
courseList = await _context.Course
.Where(a=>a.CategoryId==categoryId.Value)
.ToListAsync()
}
vm.Courses = GetCourseVms(courseList);
return View(vm);
}
private IEnumerable<CourseVm> GetCourseVms(IEnumerable<Course> courses)
{
return courses.Select(a=>new CourseVm { Id=a.Id, Name =a.Name});
}
我使用GetCourseVms
方法将Course实体映射到CourseVm视图模型对象。如果您愿意,可以使用Auto mapper等库来实现。
现在,在您的视图中,强烈键入CourseListVm,我们将使用DropDownListFor
辅助方法呈现类别的下拉列表。如果您正在使用asp.net核心应用程序,则可以使用Select tag helper to render the dropdown
@model CourseListVm
@using (Html.BeginForm("Index", "Courses",FormMethod.Get))
{
@Html.DropDownListFor(a=>a.CategoryId,Model.Categories,"All")
<button type="submit">Filter</button>
}
@foreach (var p in Model.Courses)
{
<p>@p.Id</p>
<p>@p.Name</p>
}
当用户选择一个类别并单击提交按钮时,表单将被提交到URL中具有所选类别ID的索引操作,操作方法代码将使用该操作创建要过滤的课程的过滤集合在视图中。