Chuyển đến nội dung chính

Umbraco 13: Gọi Content Delivery API lấy một Content Item và phân tích JSON - Day 4.1

Trong Day 4, chúng ta đã có cái nhìn tổng quan về Content Delivery API của Umbraco 13. Bây giờ, chúng ta sẽ bắt đầu thực hành với một thao tác cụ thể: lấy thông tin của một content item và đọc hiểu JSON mà API trả về.

Project thực hành của chúng ta là Bookstore, với cấu trúc nội dung đã tạo trong Umbraco Backoffice:

  • Bookstore Home: node trang chủ.
  • Lịch sử: category sách lịch sử.
  • Triết học: category sách triết học.

Trong bài này, chúng ta sẽ sử dụng Bookstore Home làm ví dụ. Sau khi hoàn thành, bạn sẽ hiểu cách gọi endpoint, lấy GUID của content item, đọc các trường trong JSON response và xử lý một số lỗi thường gặp.

1. Hiểu mục tiêu của bài thực hành

Trong Umbraco truyền thống, ứng dụng có thể sử dụng dữ liệu CMS để render HTML trực tiếp từ phía server. Với mô hình Headless CMS, ứng dụng khác có thể gọi API để lấy dữ liệu nội dung dưới dạng JSON.

Luồng hoạt động trong bài này như sau:

flowchart TD A["Umbraco Backoffice"] --> B["Bookstore Home"] B --> C["Content Delivery API"] C --> D["HTTP GET Request"] D --> E["JSON Response"] E --> F["Phân tích dữ liệu"]

Chúng ta chưa cần xây dựng giao diện Next.js hay React. Mục tiêu hiện tại chỉ là xác minh rằng Umbraco có thể trả về đúng content item và hiểu dữ liệu nhận được.

2. Bước 1: Kiểm tra Content Delivery API

Trước khi gọi API, hãy kiểm tra cấu hình trong file appsettings.json của project Umbraco.

{
  "Umbraco": {
    "CMS": {
      "DeliveryApi": {
        "Enabled": true
      }
    }
  }
}

Nếu project đã bật Content Delivery API từ Day 4, bạn không cần thêm lại cấu hình này.

Tiếp theo, hãy bảo đảm project đang chạy và ghi lại địa chỉ HTTPS thực tế. Ví dụ, nếu project chạy tại https://localhost:44366, chúng ta sẽ sử dụng địa chỉ đó trong các request bên dưới.

Lưu ý: Port trong ví dụ chỉ mang tính minh họa. Hãy thay bằng port của project trên máy bạn.

3. Bước 2: Lấy GUID của Bookstore Home

Content Delivery API sử dụng GUID để xác định một content item. GUID này khác với integer node ID mà bạn có thể gặp trong một số khu vực của Umbraco.

Để lấy GUID của Bookstore Home:

  1. Mở Umbraco Backoffice.
  2. Đi đến Content Tree.
  3. Chọn node Bookstore Home.
  4. Mở tab Info và tìm thông tin định danh của content item.
  5. Sao chép GUID thực tế của node.

GUID trong bài viết không được cố định vì mỗi project có dữ liệu riêng. Do đó, hãy sử dụng GUID vừa lấy được thay vì sao chép một GUID ví dụ trên Internet.

Ví dụ dưới đây minh họa một GUID có định dạng hợp lệ:

256048db-162d-4cc7-b7e3-c4537fb970bd

Đây chỉ là GUID minh họa. Nó không nhất thiết trùng với GUID của Bookstore Home trong project của bạn.

4. Bước 3: Gọi API lấy một content item

Umbraco Content Delivery API cung cấp endpoint lấy một content item theo GUID:

GET /umbraco/delivery/api/v2/content/item/{id}

Trong đó:

  • /umbraco/delivery/api/v2/content/item/ là phần đường dẫn endpoint.
  • {id} là GUID của content item cần lấy.

Giả sử GUID thật của Bookstore Home đã được thay vào biến BOOKSTORE_HOME_GUID, URL request sẽ có dạng:

GET https://localhost:44366/umbraco/delivery/api/v2/content/item/BOOKSTORE_HOME_GUID

Thay BOOKSTORE_HOME_GUID bằng GUID thật. Không gửi nguyên chuỗi placeholder này trong request.

4.1. Thử bằng trình duyệt

Nếu Content Delivery API cho phép truy cập công khai theo cấu hình hiện tại, bạn có thể dán URL đầy đủ vào trình duyệt để kiểm tra response.

Nếu API được cấu hình yêu cầu API key, trình duyệt thông thường không thuận tiện để thêm header tùy chỉnh. Trong trường hợp đó, hãy dùng Swagger, Postman hoặc một công cụ gửi HTTP request có hỗ trợ header.

4.2. Thử bằng curl

Bạn cũng có thể dùng lệnh curl trong terminal. Ví dụ trên Windows PowerShell:

curl.exe -k "https://localhost:44366/umbraco/delivery/api/v2/content/item/BOOKSTORE_HOME_GUID"

Hãy thay port và GUID bằng giá trị thật của project.

Tùy chọn -k bỏ qua việc xác minh chứng chỉ TLS. Chỉ nên dùng trong môi trường local khi bạn đang sử dụng chứng chỉ phát triển chưa được hệ điều hành tin cậy. Không sử dụng tùy chọn này như giải pháp bảo mật cho môi trường production.

Nếu API yêu cầu API key, bạn cần thêm header phù hợp:

curl.exe -k `
  -H "Api-Key: YOUR_SECRET_API_KEY" `
  "https://localhost:44366/umbraco/delivery/api/v2/content/item/BOOKSTORE_HOME_GUID"

Chỉ thêm header khi cấu hình API của bạn yêu cầu key. Không ghi API key thật vào bài blog hoặc commit secret vào Git.

5. Bước 4: Đọc JSON Response

Nếu request thành công, API sẽ trả về JSON mô tả content item. Ví dụ rút gọn dưới đây minh họa cấu trúc response có thể gặp:

{
  "name": "Bookstore Home",
  "createDate": "2026-10-01T08:00:00",
  "updateDate": "2026-10-15T10:30:00",
  "route": {
    "path": "/",
    "startItem": {
      "id": "YOUR-BOOKSTORE-HOME-GUID",
      "path": "bookstore-home"
    }
  },
  "id": "YOUR-BOOKSTORE-HOME-GUID",
  "contentType": "bookstoreHome",
  "properties": {
    "siteTitle": "Nhà sách Trực tuyến",
    "welcomeText": "Chào mừng bạn đến với cửa hàng sách!"
  },
  "cultures": {}
}

Đây là JSON minh họa đã rút gọn, không phải response được lấy trực tiếp từ project. GUID, tên property, route và giá trị ngày tháng cần được đối chiếu với response thực tế của bạn.

Hãy phân tích các trường quan trọng sau.

5.1. Trường name

{
  "name": "Bookstore Home"
}

name là tên của content item. Với node đang thực hành, giá trị mong đợi là Bookstore Home nếu tên node chưa được thay đổi.

Trường này thường hữu ích khi cần hiển thị tên nội dung hoặc xác định nhanh một item trong kết quả API.

5.2. Trường id

{
  "id": "YOUR-BOOKSTORE-HOME-GUID"
}

id là GUID định danh content item. Khi gọi endpoint theo ID, bạn cần truyền GUID này, không phải integer node ID.

GUID cũng hữu ích khi cần tham chiếu đến một item cụ thể mà không phụ thuộc vào tên hiển thị của nó.

5.3. Trường contentType

{
  "contentType": "bookstoreHome"
}

contentType là alias của Document Type tương ứng.

Ví dụ, nếu Document Type của Bookstore Home có alias bookstoreHome, response sẽ phản ánh alias đó. Nếu project của bạn dùng alias khác, giá trị trong response cũng sẽ khác.

Thông tin này giúp ứng dụng tiêu thụ API nhận biết loại nội dung đang được trả về. Tuy nhiên, việc quyết định render giao diện nào vẫn thuộc về ứng dụng sử dụng API.

5.4. Trường route

{
  "route": {
    "path": "/",
    "startItem": {
      "id": "YOUR-BOOKSTORE-HOME-GUID",
      "path": "bookstore-home"
    }
  }
}

route.path thể hiện đường dẫn của content item theo cấu hình route hiện tại.

Với node trang chủ, route có thể là /. Các category hoặc bài viết có thể có route khác, tùy cấu trúc nội dung và cấu hình website.

startItem cung cấp thông tin về root content item trong ngữ cảnh route. Thông tin này đặc biệt hữu ích khi website có nhiều root node hoặc nhiều site.

Không nên mặc định mọi content item đều có cùng route hoặc mọi website đều có một root node duy nhất.

5.5. Trường properties

{
  "properties": {
    "siteTitle": "Nhà sách Trực tuyến",
    "welcomeText": "Chào mừng bạn đến với cửa hàng sách!"
  }
}

properties chứa dữ liệu của các property được cấu hình trên Document Type và được API trả về.

Ví dụ, nếu Document Type có các property alias siteTitle và welcomeText, JSON có thể chứa các giá trị tương ứng.

Tuy nhiên, nếu Document Type thực tế của bạn không có các alias này thì chúng sẽ không tự xuất hiện. Hãy xem response thật để xác định những property đang được trả về.

Kiểu dữ liệu của property phụ thuộc vào Data Type hoặc property editor. Giá trị có thể là chuỗi, số, boolean, mảng, object hoặc null.

5.6. Trường createDate và updateDate

{
  "createDate": "2026-10-01T08:00:00",
  "updateDate": "2026-10-15T10:30:00"
}

Hai trường này biểu thị thời điểm tạo và cập nhật content item. Định dạng timestamp cụ thể trong response có thể có hoặc không có phần múi giờ, tùy cách dữ liệu được serialize.

Không nên suy luận rằng ngày cập nhật gần nhất nhất thiết là ngày nội dung được publish lần cuối. Nếu cần theo dõi thời điểm publish, hãy xác định trường hoặc cơ chế phù hợp cho mục đích đó.

5.7. Trường cultures

{
  "cultures": {}
}

cultures cung cấp thông tin liên quan đến các culture được cấu hình cho content item, bao gồm route variant trong trường hợp nội dung có biến thể ngôn ngữ.

Giá trị thực tế phụ thuộc vào cấu hình Languages, Document Type, property variation và các bản dịch đã được publish. Vì project của chúng ta sẽ có phần học riêng về multilingual, ở bài này chỉ cần nhận diện trường dữ liệu và ghi lại giá trị thực tế.

6. Bước 5: Phân biệt dữ liệu trong Backoffice và JSON

Một câu hỏi thường gặp là: tại sao JSON không giống hoàn toàn với giao diện chỉnh sửa nội dung trong Umbraco?

Nguyên nhân là Backoffice và Content Delivery API phục vụ hai mục đích khác nhau:

  • Backoffice: cung cấp giao diện cho biên tập viên quản lý nội dung, Data Type và trạng thái publish.
  • Content Delivery API: cung cấp dữ liệu đã publish cho ứng dụng tiêu thụ thông qua một cấu trúc JSON.

Vì vậy, không phải mọi thông tin nhìn thấy trong Backoffice đều được trả về nguyên dạng trong JSON.

Nếu một property không xuất hiện trong response, hãy kiểm tra:

  1. Property đó có thuộc Document Type của node đang truy vấn không?
  2. Property có được nhập giá trị và publish chưa?
  3. Alias của property có đúng không?
  4. Request có sử dụng tham số fields để giới hạn property không?
  5. Property editor đó trả về kiểu dữ liệu nào trong Content Delivery API?

7. Bước 6: Xử lý các lỗi thường gặp

7.1. Nhận lỗi 404 Not Found

Nếu request trả về 404, hãy kiểm tra:

  • GUID có đúng với Bookstore Home không?
  • Bạn có vô tình dùng integer node ID thay vì GUID không?
  • Content item có tồn tại và đã publish chưa?
  • URL endpoint có đúng không?
  • Port có đúng với project đang chạy không?

Đừng vội thay đổi cấu hình API nếu nguyên nhân chỉ là GUID sai.

7.2. Nhận lỗi 401 Unauthorized

Lỗi 401 có thể xuất hiện khi API đang được bảo vệ và request không cung cấp API key hợp lệ.

Hãy kiểm tra cấu hình PublicAccess, giá trị ApiKey và header Api-Key trong request. Không nên vô hiệu hóa bảo vệ chỉ để làm cho một request thử nghiệm chạy được mà chưa hiểu tác động bảo mật.

7.3. Request thành công nhưng property không có dữ liệu

Trường hợp này khác với lỗi 404. Content item có thể đã được tìm thấy, nhưng property không xuất hiện hoặc có giá trị null.

Hãy kiểm tra alias, dữ liệu đã nhập, trạng thái publish và Data Type. Nếu request sử dụng fields, hãy thử bỏ tham số đó để kiểm tra response đầy đủ trước.

8. Bài tập thực hành

Hãy thực hiện các bước sau trên project Bookstore của bạn:

  1. Lấy GUID thật của Bookstore Home từ Backoffice.
  2. Gọi endpoint /umbraco/delivery/api/v2/content/item/{id}.
  3. Ghi lại giá trị thực tế của name, id, contentType và route.path.
  4. Liệt kê các property thực sự xuất hiện trong properties.
  5. Kiểm tra giá trị cultures và ghi lại kết quả.
  6. Thử gọi API bằng một GUID không tồn tại và quan sát response.
  7. Nếu API được bảo vệ, thử request thiếu API key trong môi trường local và ghi lại kết quả.

Bạn có thể lưu kết quả thực hành theo bảng sau:

Trường Giá trị trong project Ý nghĩa
name Ghi giá trị thực tế Tên content item
id Ghi GUID thật Định danh content item
contentType Ghi alias thật Loại nội dung
route.path Ghi route thật Đường dẫn nội dung
properties Liệt kê property thật Dữ liệu biên tập
cultures Ghi response thật Thông tin culture nếu có

9. Tổng kết Day 4.1

Qua bài thực hành này, chúng ta đã làm quen với cách lấy một content item bằng Content Delivery API của Umbraco 13.

Những kiến thức quan trọng cần ghi nhớ:

  • Endpoint lấy một item là /umbraco/delivery/api/v2/content/item/{id}.
  • Tham số id là GUID của content item, không phải integer node ID.
  • JSON response gồm thông tin cơ bản, route, properties và thông tin culture nếu có.
  • Danh sách property phụ thuộc vào Document Type, dữ liệu đã publish và các tham số truy vấn.
  • Khi gặp lỗi, cần kiểm tra URL, GUID, trạng thái publish và cấu hình bảo vệ API trước khi thay đổi hệ thống.

Điểm quan trọng nhất là hãy sử dụng response thật của project để học. JSON trong bài viết chỉ là ví dụ minh họa; tên property và giá trị thực tế cần được xác minh từ API của bạn.

10. Bài tiếp theo: Day 4.2 — Truy vấn danh sách Content Items

Sau khi đã biết cách lấy một content item theo GUID, bước tiếp theo là lấy nhiều item cùng lúc.

Trong Day 4.2, chúng ta sẽ sử dụng endpoint /umbraco/delivery/api/v2/content và selector fetch=children để truy vấn hai category Lịch sử và Triết học bên dưới Bookstore Home.

Đây là bước chuyển từ việc lấy một trang đơn lẻ sang việc truy vấn dữ liệu có cấu trúc, làm nền tảng cho các bài tiếp theo về multilingual và API phục vụ ứng dụng.

Tài liệu tham khảo

Nhận xét

Bài đăng phổ biến từ blog này

[ASP.NET MVC] Authentication và Authorize

Một trong những vấn đề bảo mật cơ bản nhất là đảm bảo những người dùng hợp lệ truy cập vào hệ thống. ASP.NET đưa ra 2 khái niệm: Authentication và Authorize Authentication xác nhận bạn là ai. Ví dụ: Bạn có thể đăng nhập vào hệ thống bằng username và password hoặc bằng ssh. Authorization xác nhận những gì bạn có thể làm. Ví dụ: Bạn được phép truy cập vào website, đăng thông tin lên diễn đàn nhưng bạn không được phép truy cập vào trang mod và admin.

Tổng hợp một số kiến thức lập trình về Amibroker

Giới thiệu về Amibroker Amibroker theo developer Tomasz Janeczko được xây dựng dựa trên ngôn ngữ C. Vì vậy bộ code Amibroker Formula Language sử dụng có syntax khá tương đồng với C, ví dụ như câu lệnh #include để import hay cách gói các object, hàm trong các block {} và kết thúc câu lệnh bằng dấu “;”. AFL trong Amibroker là ngôn ngữ xử lý mảng (an array processing language). Nó hoạt động dựa trên các mảng (các dòng/vector) số liệu, khá giống với cách hoạt động của spreadsheet trên excel.

ASP.NET MVC: Cơ bản về Validation

Validation (chứng thực) là một tính năng quan trọng trong ASP.NET MVC và được phát triển trong một thời gian dài. Validation vắng mặt trong phiên bản đầu tiên của asp.net mvc và thật khó để tích hợp 1 framework validation của một bên thứ 3 vì không có khả năng mở rộng. ASP.NET MVC2 đã hỗ trợ framework validation do Microsoft phát triển, tên là Data Annotations. Và trong phiên bản 3, framework validation đã hỗ trợ tốt hơn việc xác thực phía máy khách, và đây là một xu hướng của việc phát triển ứng dụng web ngày nay.