为微软ContosoUniversity例子加上学生自选课程计划

把ContosoUniversity例子过了一遍,好象还是有很多东西未能理解,决定自己随便加个功能看可以自己完成不....

从github的例子中clone下来ContosoUniversity项目,使用CodeFirst进行迁移后就可以得到一个正常运作的例子。

  增加的课程计划 StudentCoursePlan.cs

    public partial class StudentCoursePlan
    {
        public int Id { get; set; }
        public int CourseId { get; set; }
        public int StudentId { get; set; }
        public Student Student { get; set; }
        public Course Course { set; get; }
    }

  在SchoolContext.cs中加入定义

public DbSet<StudentCoursePlan> StudentCoursePlan { get; set; }

增加在列出学生列表时选择指定学生,可为其增加自己选择选修课程,并计算已获取多少学分功能

  在Student目录下的Index.cshtml文件添加一个按钮,按下后可以弹出一个可选定的课程列表

<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> |
    <a asp-action="Plan" asp-route-id="@item.ID">Plan</a>
</td>

  在Students.cs中增加对StudentCoursePlan的关联

public ICollection<StudentCoursePlan> StudentCoursePlan { get; set; }

  在StudentsController.cs中增加Plan的Get动作

        public async Task<IActionResult> Plan(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }
            var student = await _context.Students
                .Include(s => s.StudentCoursePlan)
                    .ThenInclude(e => e.Course)
                .Include(e => e.Enrollments)
                    .ThenInclude(e => e.Course)
                .AsNoTracking()
                .SingleOrDefaultAsync(m => m.ID == id);
            if (student == null)
            {
                return NotFound();
            }
            PopulatePlanedCourse(student);
            return View(student);
        }
        private void PopulatePlanedCourse(Student student)
        {
            List<StudentCoursePlanShowData> StudentCourseShow = new List<StudentCoursePlanShowData>();
            var selectedCourse = student.StudentCoursePlan.Select(s => s.Course);
            var grade = "";
            int? takedCredits = null;
            int? sumCredits = null;
            foreach (var course in selectedCourse)
            {
                if (course.Enrollments != null)
                {
                    grade = student.Enrollments.Where(i => i.CourseID == course.CourseID).SingleOrDefault().Grade.ToString();
                    takedCredits = course.Credits / 5 * (5 - (int)student.Enrollments.Where(i => i.CourseID == course.CourseID).SingleOrDefault().Grade);
                    sumCredits = (sumCredits ?? 0) + takedCredits;
                }
                else
                {
                    grade = "";
                    takedCredits = null;
                }
                StudentCourseShow.Add(new StudentCoursePlanShowData
                {
                    CourseID = course.CourseID,
                    Title = course.Title,
                    Grade = grade,
                    TakedCredits = takedCredits
                });
            }
            ViewData["StudentCourseShow"] = StudentCourseShow;
            ViewData["showNoData"] = StudentCourseShow.Count > 0 ? "hide" : "alert alert-warning";
            ViewData["sumCredits"] = sumCredits;
            ViewData["studentID"] = student.ID;
            ViewData["UnselectedCourse"] = new List<StudentCoursePlanShowData>();
        }

  为了显示已选定的课程列表,在Models->SchoolViewModels目录下建立StudentCoursePlanShowData.cs

    public class StudentCoursePlanShowData
    {
        public int CourseID { get; set; }
        public string Title { get; set; }
        public string Grade { get; set; }
        public int? TakedCredits { get; set; }
    }

  Plan.cshtml

@model ContosoUniversity.Models.Student
@using ContosoUniversity.Models.SchoolViewModels;
@{
    ViewData["Title"] = "Student Course Plan";
}

<h2>The course that you ordered ... </h2>

<div>
    <h4>Student</h4>
    <hr />
    <p>Full Name : @Html.DisplayFor(model => model.FullName)</p>
    <span class="badge badge-info">Course List</span>
    <div class="@ViewData["showNoData"]">--没有数据--</div>
    <input type="hidden" value=@Html.DisplayFor(model => model.ID)>
    <table class="table table-bordered">
        @if (((List<StudentCoursePlanShowData>)ViewData["StudentCourseShow"]).Count > 0)
        {
            <thead class="thead-inverse">
                <tr>
                    <th>CourseID</th>
                    <th>Title</th>
                    <th>Grade</th>
                    <th>TakedCredits</th>
                </tr>
            </thead>
        }
        @foreach (var item in (List<StudentCoursePlanShowData>)ViewData["StudentCourseShow"])
        {
            <tr>
                <td>
                    @Html.DisplayFor(ModeItem => item.CourseID)
                </td>
                <td>
                    @Html.DisplayFor(ModelItem => item.Title)
                </td>
                <td>
                    @Html.DisplayFor(ModelItem => item.Grade)
                    <div>

                    </div>
                </td>
                <td>
                    @Html.DisplayFor(ModelItem => item.TakedCredits)
                </td>
            </tr>
        }
    </table>
    @if (((List<StudentCoursePlanShowData>)ViewData["StudentCourseShow"]).Count > 0)
    {
        <div class="alert alert-success" role="alert">
            <strong>Total TookCredts:</strong>@ViewData["sumCredits"]
        </div>
    }

    <div class="nav-divider">
        <input class="btn btn-primary" type="button" id="btnPost" value="Post Test" data-toggle="modal" data-target="#modalSelectCourse" />
        <a style="margin-left:20px" asp-action="Index">Back to List</a>

        @Html.AntiForgeryToken()
        @section Scripts{
            @{ await Html.RenderPartialAsync("_ValidationScriptsPartial");}
            <script type="text/javascript" language="JavaScript">
            $(document).ready(function () {
                $("#btnPost").on('click', function () {
                    $("#dvShowData").load('@Url.Action("GetUnselectedCourse", "Students", new { id = Model.ID })');
                });
            });
            </script>
        }
    </div>
    <!-- Modal -->
    <div class="modal" id="modalSelectCourse" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="modalLabel">Course List</h5>
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">×</span>
                    </button>
                </div>
                <form asp-action="Plan">
                    <div class="modal-body">
                        <div id="dvShowData">
                            @{
                                await Html.PartialAsync("resultsUnselectedCourse", Model);
                            }
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                        <button type="submit" class="btn btn-primary">Save changes</button>
                    </div>
                </form>
            </div>
        </div>
    </div>

</div>

 

  加粗部分的js语句调用了GetUnselectedCourse方法生成未经选定的课程列表,按下Post Test按钮时弹出部分视图resultsUnselectedCourse.cshtml来显示,部分视图代码如下:

@model ContosoUniversity.Models.Student;
@using ContosoUniversity.Models.SchoolViewModels;
<h2>FullName:@Model.FullName</h2>
<table class="table">
    <thead>
        <tr>
            <th>CourseID</th>
            <th>Title</th>
            <th>Credits</th>
            <th>Select</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var course in ((List<StudentCoursePlanShowData>)ViewData["UnselectedCourse"]))
        {
            <tr>
                <td>@course.CourseID</td>
                <td>@course.Title</td>
                <td>@course.TakedCredits</td>
                <td>
                    <input class="checkbox" type="checkbox" name="stringSelectedCourse" value="@course.CourseID" />
                </td>
            </tr>
        }
    </tbody>
</table>

  列出未经选定课程的方法

        public async Task<IActionResult> GetUnselectedCourse(int? id)
        {
            var allCourses = _context.Courses;
            var viewModel = new List<StudentCoursePlanShowData>();
            var student = await _context.Students.Include(s => s.StudentCoursePlan).AsNoTracking().SingleOrDefaultAsync(m => m.ID == id);

            if (student != null)
            {
                var studentSelectedCourse = new HashSet<int>(student.StudentCoursePlan.Select(c => c.CourseId));

                foreach (var course in allCourses)
                {
                    if (!studentSelectedCourse.Contains(course.CourseID))
                        viewModel.Add(new StudentCoursePlanShowData
                        {
                            CourseID = course.CourseID,
                            Title = course.Title,
                            TakedCredits = course.Credits
                        });
                }
            }
            ViewData["UnselectedCourse"] = viewModel;
            return PartialView("resultsUnselectedCourse", student);
        }

  选定了课程按下 Save Change 按钮时 激发 Plan 的Post 方法,记录到StudentCoursePlan表

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Plan(int? id, string[] stringSelectedCourse)
        {
            if (id == null)
            { return NotFound(); }
            if (ModelState.IsValid)
            {
                UpdatePlanCourse(stringSelectedCourse, id ?? 0);
                try
                {

                    await _context.SaveChangesAsync();
                    return RedirectToAction(nameof(Plan));
                }
                catch (DbUpdateException)
                {
                    ModelState.AddModelError("", "更新资料失败");
                }
            }
            var student = await _context.Students
                .Include(s => s.StudentCoursePlan)
                    .ThenInclude(e => e.Course)
                .Include(e => e.Enrollments)
                    .ThenInclude(e => e.Course)
                .AsNoTracking()
                .SingleOrDefaultAsync(m => m.ID == id);
            PopulatePlanedCourse(student);
            return View(student);
        }

        private void UpdatePlanCourse(string[] stringSelectedCourse, int studentID)
        {
            int j;
            foreach (var course in stringSelectedCourse)
            {
                if (!int.TryParse(course, out j))
                    j = 0;
                _context.Add(new StudentCoursePlan
                {
                    CourseId = j,
                    StudentId = studentID
                });
            }
        }

嗯,到这里就完成了,下一步看怎么完善一下它吧!

 

posted @ 2018-05-16 16:29  CMD2018  阅读(376)  评论(0编辑  收藏  举报