Search code examples
c#asp.net-core-webapireturn-type

What should I return in this method to get department and list of students present in department?


I have implemented a core web api with two entities Student and Department and have implemented One to Many relationship where a department can have number of students.

I have created a response model named DepartmentStudentsResponse

DepartmentStudentsResponse.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Students.Models
{
    public class DepartmentStudentsResponse
    {
        public Department department { get; set; }
        public List<Student> students { get; set; }
    }
}

I want to implement GetStudents(int id) method in which particular department id will be provided and it should return that department with listOfstudents in it.

In GetStudents(int id) method, departmentStudents.department = department.Result;, departmentStudents.students = listOfStudents.Result; why do we need .Result? How can I imlement the same without .Result?

DeparmentController.cs GetStudents(int id)

[HttpGet("{id}")]
//[Route("DepartmentWithStudent")]
public async Task<ActionResult<Student>> GetStudents(int id)
{
    DepartmentStudentsResponse departmentStudents = new DepartmentStudentsResponse();

    var department =  _context.Departments.FindAsync(id);
    if (department != null)
    {
        departmentStudents.department = department.Result;

        var listOfStudents = _context.Students.Where(x => x.DepartmentId == id).ToListAsync();
        departmentStudents.students = listOfStudents.Result;
        //return departmentStudents;
    }
    else
    {
        return NotFound();
    }
 }

Solution

  • So far everything needed to satisfy you requirements are present in the shown method. A few changes need to be made to make it functional.

    • You do not need to use .Result.

      Mixing async-await with blocking calls like .Result can cause deadlocks. Those asynchronous calls should be awaited.

    • The action's return type needs to match the desired type.

    • Use an appropriate, unique route template for the action to avoid route conflicts.

    For example

    [Route("api/[controller]")]
    [ApiController]
    public class DepartmentController : ControllerBase {
    
        //...
    
        //GET api/department/5/students
        [HttpGet("{id:int}/students")]     
        public async Task<ActionResult<DepartmentStudentsResponse>> GetStudents(int id) {
            var department =  await _context.Departments.FindAsync(id);
            if (department == null)
                return NotFound();
    
            DepartmentStudentsResponse departmentStudents = new DepartmentStudentsResponse() {
                department = department
            };
            var listOfStudents = await _context.Students.Where(x => x.DepartmentId == id).ToListAsync();
            departmentStudents.students = listOfStudents;
            return departmentStudents;            
         }
    }