ASP.NET Web API - Triển khai phương thức Get

Triển khai phương thức Get

Phần này là phần tiếp theo của phần trước, trong đó chúng ta đã tạo cơ sở hạ tầng cần thiết cho Web API của mình.

Trong phần này, chúng ta sẽ triển khai các phương thức hành động Get trong lớp bộ điều khiển Web API của mình để xử lý các yêu cầu HTTP GET.

Theo quy ước đặt tên của Web API, phương thức hành động bắt đầu bằng từ "Get" sẽ xử lý yêu cầu HTTP GET. Chúng ta có thể chỉ đặt tên là Get hoặc bất kỳ hậu tố nào. Hãy thêm phương thức hành động Get đầu tiên của chúng ta và đặt tên là GetAllStudents vì nó sẽ trả về tất cả học sinh từ DB. Việc tuân theo một phương pháp đặt tên phù hợp sẽ tăng khả năng đọc và bất kỳ ai cũng có thể dễ dàng hiểu được mục đích của một phương thức.

Phương thức hành động GetAllStudents() sau đây trong lớp StudentController (mà chúng ta đã tạo trong phần trước) sẽ trả về tất cả học sinh từ cơ sở dữ liệu bằng Entity Framework.

Ví dụ: Phương thức Get trong Controller API Web

public class StudentController : ApiController
{
    public IHttpActionResult GetAllStudents ()
    {
        IList<StudentViewModel> students = null;

        using (var ctx = new SchoolDBEntities())
        {
            students = ctx.Students.Include("StudentAddress")
                        .Select(s => new StudentViewModel()
                        {
                            Id = s.StudentID,
                            FirstName = s.FirstName,
                            LastName = s.LastName
                        }).ToList<StudentViewModel>();
        }

        if (students.Count == 0)
        {
            return NotFound();
        }

        return Ok(students);
    }
}

Như bạn có thể thấy trong ví dụ trên, phương thức GetAllStudents() trả về tất cả các sinh viên bằng EF. Nếu không có sinh viên nào tồn tại trong DB thì nó sẽ trả về phản hồi 404 NotFound, nếu không thì nó sẽ trả về phản hồi 200 OK với dữ liệu sinh viên. Các phương thức NotFound() và Ok() được định nghĩa trong ApiController trả về phản hồi 404 và 200 tương ứng.


Trong cơ sở dữ liệu, mỗi sinh viên có 0 hoặc 1 địa chỉ. Giả sử, bạn muốn triển khai một phương thức GET khác để lấy tất cả Sinh viên có địa chỉ của họ thì bạn có thể tạo một phương thức Get khác như được hiển thị bên dưới.

Ví dụ: Phương thức Get trong Controller API Web

public class StudentController : ApiController
{
      
    public IHttpActionResult GetAllStudents ()
    {
        IList<StudentViewModel> students = null;
        
        using (var ctx = new SchoolDBEntities())
        {
            students = ctx.Students.Include("StudentAddress")
                        .Select(s => new StudentViewModel()
                        {
                            Id = s.StudentID,
                            FirstName = s.FirstName,
                            LastName = s.LastName
                        }).ToList<StudentViewModel>();
        }

        if (students.Count == 0)
        {
            return NotFound();
        }

        return Ok(students);
    }

    public IHttpActionResult GetAllStudentsWithAddress()
    {
        IList<StudentViewModel> students = null;

        using (var ctx = new SchoolDBEntities())
        {
            students = ctx.Students.Include("StudentAddress").Select(s => new StudentViewModel()
            {
                Id = s.StudentID,
                FirstName = s.FirstName,
                LastName = s.LastName,
                Address = s.StudentAddress == null ? null : new AddressViewModel()
                {
                    StudentId = s.StudentAddress.StudentID,
                    Address1 = s.StudentAddress.Address1,
                    Address2 = s.StudentAddress.Address2,
                    City = s.StudentAddress.City,
                    State = s.StudentAddress.State
                }
            }).ToList<StudentViewModel>();
        }


        if (students.Count == 0)
        {
            return NotFound();
        }

        return Ok(students);
    }
}

Ví dụ API web ở trên sẽ biên dịch mà không có lỗi nhưng khi bạn thực hiện yêu cầu HTTP GET thì nó sẽ phản hồi với lỗi tìm thấy nhiều hành động sau.

Điều này là do bạn không thể có nhiều phương thức hành động với cùng số lượng tham số với cùng loại. Cả hai phương thức hành động trên đều không bao gồm bất kỳ tham số nào. Vì vậy, Web API không hiểu phương thức nào để thực thi cho yêu cầu HTTP GET http://localhost:64189/api/student.

Ví dụ sau minh họa cách xử lý loại tình huống này.

Ví dụ: Phương thức Get trong Controller API Web

public class StudentController : ApiController
{

    public StudentController()
    {
    }

    public IHttpActionResult GetAllStudents(bool includeAddress = false)
    {
        IList<StudentViewModel> students = null;

        using (var ctx = new SchoolDBEntities())
        {
            students = ctx.Students.Include("StudentAddress")
                       .Select(s => new StudentViewModel()
                        {
                            Id = s.StudentID,
                            FirstName = s.FirstName,
                            LastName = s.LastName,
                            Address = s.StudentAddress == null || includeAddress == false ? null : new AddressViewModel()
                            {
                                StudentId = s.StudentAddress.StudentID,
                                Address1 = s.StudentAddress.Address1,
                                Address2 = s.StudentAddress.Address2,
                                City = s.StudentAddress.City,
                                State = s.StudentAddress.State
                            }
                        }).ToList<StudentViewModel>();
        }

        if (students.Count == 0)
        {
            return NotFound();
        }

        return Ok(students);
    }
}

Như bạn có thể thấy, phương thức hành động GetAllStudents bao gồm tham số includeAddress với giá trị mặc định là false. Nếu một yêu cầu HTTP chứa tham số includeAddress trong chuỗi truy vấn với giá trị true thì nó sẽ trả về tất cả học sinh có địa chỉ của học sinh đó, nếu không, nó sẽ trả về học sinh không có địa chỉ.

Ví dụ: http://localhost:64189/api/student (64189 là số cổng có thể khác ở máy cục bộ của bạn) sẽ trả về tất cả học sinh không có địa chỉ như hiển thị bên dưới.

Truy cập phương thức GET của Web API trong trình duyệt

Yêu cầu HTTP http://localhost:64189/api/student?includeAddress=true sẽ trả về tất cả học sinh có địa chỉ như hiển thị bên dưới.

 

Triển khai nhiều phương thức GET

Như đã đề cập, bộ điều khiển Web API có thể bao gồm nhiều phương thức Get với các tham số và kiểu khác nhau.

Hãy thêm các phương thức hành động sau vào StudentController để chứng minh cách Web API xử lý nhiều yêu cầu HTTP GET.

Phương thức hành động Mục đích
GetStudentById(int id) Trả về học sinh có id khớp với id đã chỉ định.
GetAllStudents(string name) Trả về danh sách học sinh có tên trùng với tên đã chỉ định.
GetAllStudentsInSameStandard(int standardId) Trả về danh sách học sinh đạt tiêu chuẩn đã chỉ định.

Ví dụ sau đây triển khai các phương thức hành động trên.

Ví dụ: Nhiều phương thức Get trong Web API Controller

public class StudentController : ApiController
{
    public StudentController()
    {
    }

    public IHttpActionResult GetAllStudents(bool includeAddress = false)
    {
        IList<StudentViewModel> students = null;

        using (var ctx = new SchoolDBEntities())
        {
            students = ctx.Students.Include("StudentAddress").Select(s => new StudentViewModel()
            {
                Id = s.StudentID,
                FirstName = s.FirstName,
                LastName = s.LastName,
                Address = s.StudentAddress == null || includeAddress == false ? null : new AddressViewModel()
                {
                    StudentId = s.StudentAddress.StudentID,
                    Address1 = s.StudentAddress.Address1,
                    Address2 = s.StudentAddress.Address2,
                    City = s.StudentAddress.City,
                    State = s.StudentAddress.State
                }
            }).ToList<StudentViewModel>();
        }

        if (students == null)
        {
            return NotFound();
        }

        return Ok(students);
    }

    public IHttpActionResult GetStudentById(int id)
    {
        StudentViewModel student = null;

        using (var ctx = new SchoolDBEntities())
        {
            student = ctx.Students.Include("StudentAddress")
                .Where(s => s.StudentID == id)
                .Select(s => new StudentViewModel()
                {
                    Id = s.StudentID,
                    FirstName = s.FirstName,
                    LastName = s.LastName
                }).FirstOrDefault<StudentViewModel>();
        }

        if (student == null)
        {
            return NotFound();
        }

        return Ok(student);
    }

    public IHttpActionResult GetAllStudents(string name)
    {
        IList<StudentViewModel> students = null;

        using (var ctx = new SchoolDBEntities())
        {
            students = ctx.Students.Include("StudentAddress")
                .Where(s => s.FirstName.ToLower() == name.ToLower())
                .Select(s => new StudentViewModel()
                {
                    Id = s.StudentID,
                    FirstName = s.FirstName,
                    LastName = s.LastName,
                    Address = s.StudentAddress == null ? null : new AddressViewModel()
                    {
                        StudentId = s.StudentAddress.StudentID,
                        Address1 = s.StudentAddress.Address1,
                        Address2 = s.StudentAddress.Address2,
                        City = s.StudentAddress.City,
                        State = s.StudentAddress.State
                    }
                }).ToList<StudentViewModel>();
        }

        if (students.Count == 0)
        {
            return NotFound();
        }

        return Ok(students);
    }

    public IHttpActionResult GetAllStudentsInSameStandard(int standardId)
    {
        IList<StudentViewModel> students = null;

        using (var ctx = new SchoolDBEntities())
        {
            students = ctx.Students.Include("StudentAddress").Include("Standard").Where(s => s.StandardId == standardId)
                        .Select(s => new StudentViewModel()
                        {
                            Id = s.StudentID,
                            FirstName = s.FirstName,
                            LastName = s.LastName,
                            Address = s.StudentAddress == null ? null : new AddressViewModel()
                            {
                                StudentId = s.StudentAddress.StudentID,
                                Address1 = s.StudentAddress.Address1,
                                Address2 = s.StudentAddress.Address2,
                                City = s.StudentAddress.City,
                                State = s.StudentAddress.State
                            },
                            Standard = new StandardViewModel()
                            {
                                StandardId = s.Standard.StandardId,
                                Name = s.Standard.StandardName
                            }
                        }).ToList<StudentViewModel>();
        }

        if (students.Count == 0)
        {
            return NotFound();
        }

        return Ok(students);
    }
}

Bây giờ, Web API ở trên sẽ xử lý các yêu cầu HTTP GET sau.

HTTP GET Request URL Mô tả
http://localhost:64189/api/student Trả về tất cả học sinh không có địa chỉ liên quan.
http://localhost:64189/api/student?includeAddress=false Trả về tất cả học sinh không có địa chỉ liên quan.
http://localhost:64189/api/student?includeAddress=true Trả về tất cả học sinh có địa chỉ.
http://localhost:64189/api/student?id=123 Trả về sinh viên có id được chỉ định.
http://localhost:64189/api/student?name=steve Trả về tất cả học sinh có tên là steve.
http://localhost:64189/api/student?standardId=5 Trả về tất cả học sinh đang học lớp 5.

Tương tự như vậy, bạn có thể triển khai các phương thức Get để xử lý các yêu cầu HTTP GET khác nhau trong Web API.

Hình sau đây hiển thị yêu cầu HTTP GET trong Fiddler.

Yêu cầu Http GET trong Fiddler

Hình ảnh sau đây cho thấy phản hồi HTTP GET của yêu cầu trên trong Fiddler.

Phản hồi Http GET trong Fiddler

Tiếp theo, triển khai phương thức hành động Post để xử lý yêu cầu HTTP POST trong Web API.