Bắt đầu nhanh: Thiết lập và sử dụng Dữ liệu Danh mục API Nền tảng Microsoft Learn

Trong Bắt đầu nhanh này, bạn sẽ tìm hiểu cách thiết lập và chạy API Nền tảng Microsoft Learn, bao gồm các ví dụ để truy xuất các khóa học, lộ trình học tập, mô-đun và chứng chỉ.

Điều kiện tiên quyết

Trước khi bắt đầu, hãy đảm bảo bạn đã cài đặt những thứ sau:

  • Node.js (phiên bản 18.0.0 trở lên)

    • Node.js là thời gian chạy JavaScript cho phép bạn chạy mã JavaScript/TypeScript bên ngoài trình duyệt web. Nó được yêu cầu để thực thi các tập lệnh ví dụ và quản lý các gói thông qua npm (Trình quản lý gói nút).
    • Tải xuống từ: https://nodejs.org/
    • Xác minh cài đặt: node --version
  • dịch vụ Azure CLI

    • Giao diện Azure Command-Line (CLI) là một công cụ để quản lý tài nguyên Azure từ dòng lệnh. Trong hướng dẫn này, nó được sử dụng để xác thực danh tính của bạn để các ví dụ có thể thay mặt bạn truy cập API Nền tảng Tìm hiểu.
    • Tải xuống từ: https://learn.microsoft.com/cli/azure/install-azure-cli>
    • Xác minh cài đặt: az --version
  • Tài khoản Azure

    • Cần có tài khoản Azure có đăng ký đang hoạt động để xác thực và truy cập API Nền tảng Microsoft Learn. API sử dụng Microsoft Entra ID (trước đây là Azure Active Directory) để xác thực, yêu cầu thông tin đăng nhập Azure hợp lệ. Bạn không mất phí để truy xuất mã thông báo xác thực từ đăng ký Azure của bạn.
    • Bạn cần đăng ký Azure đang hoạt động
    • Đăng ký tại: https://azure.microsoft.com/free/
  • Visual Studio Code (tùy chọn)

    • Visual Studio Code (mã VS) là một trình soạn thảo mã nhẹ, miễn phí với thiết bị đầu cuối tích hợp, hỗ trợ IntelliSense và TypeScript. Mặc dù bạn có thể sử dụng bất kỳ trình soạn thảo văn bản và thiết bị đầu cuối nào, nhưng Visual Studio Code cung cấp trải nghiệm hợp lý để chạy các ví dụ này.
    • Tải xuống từ: https://code.visualstudio.com/
    • Xác minh cài đặt: Mở Visual Studio Code và nhấn Ctrl + ' để mở thiết bị đầu cuối tích hợp

Lưu ý

Tất cả các lệnh được viết bên dưới phải được chạy trong thiết bị đầu cuối Git Bash. Bạn có thể sử dụng thiết bị đầu cuối tích hợp của VS Code (nhấn Ctrl +'), Windows PowerShell hoặc Command Prompt.

Thiết lập dự án

Làm theo các bước sau để tạo một dự án mới và cài đặt các phần phụ thuộc cần thiết.

  1. Tạo một thư mục mới cho dự án của bạn và điều hướng đến nó.

    mkdir learn-api-examples
    cd learn-api-examples
    
  2. Khởi tạo dự án Node.js mới với cài đặt mặc định. Cờ -y tự động chấp nhận tất cả các giá trị mặc định.

    npm init -y
    
  3. Cài đặt các gói npm cần thiết (@azure/identity để xác thực, tsx để chạy TypeScript trực tiếp, typescript trình biên dịch và @types/node cho các định nghĩa kiểu).

    npm install @azure/identity tsx typescript @types/node
    
  4. Tạo một tệp mới có tên examples.ts và dán mã bên dưới. Điều này bao gồm xác thực tận dụng Thông tin xác thực mặc định Azure và một số ví dụ về khả năng danh mục có sẵn thông qua API Nền tảng Tìm hiểu.

    /**
     * Microsoft Learn Platform API Examples
     * API Version: 2023-11-01-preview
     * Base URL: https://learn.microsoft.com/api/v1
     *
     * Authentication: OAuth2 with scope https://learn.microsoft.com/.default
     */
    
    import { DefaultAzureCredential } from "@azure/identity";
    
    const API_BASE_URL = "https://learn.microsoft.com/api/v1";
    const API_VERSION = "2023-11-01-preview";
    
    // ============================================================================
    // AUTHENTICATION HELPER
    // ============================================================================
    
    async function getAccessToken(): Promise<string> {
      const credential = new DefaultAzureCredential();
      const token = await credential.getToken("https://learn.microsoft.com/.default");
      return token.token;
    }
    
    /**
     * Helper to handle API response with error checking
     */
    async function handleResponse(response: Response, label: string): Promise<void> {
      if (!response.ok) {
        const text = await response.text();
        console.log(`${label} Error: ${response.status} ${response.statusText}`);
        console.log("Response:", text || "(empty)");
        return;
      }
    
      const text = await response.text();
      if (!text) {
        console.log(`${label}: (empty response)`);
        return;
      }
    
      try {
        const data = JSON.parse(text);
        console.log(`${label}:`, JSON.stringify(data, null, 2));
      } catch (e) {
        console.log(`${label} Parse Error: Invalid JSON`);
        console.log("Raw response:", text.substring(0, 500));
      }
    }
    
    // ============================================================================
    // TRAINING ENDPOINTS
    // ============================================================================
    
    /**
     * List all courses with optional filters
     * GET /courses
     */
    async function listCourses(options?: {
      levels?: string[];
      roles?: string[];
      products?: string[];
      locale?: string;
      maxpagesize?: number;
    }): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (options?.levels) params.append("levels", options.levels.join(","));
      if (options?.roles) params.append("roles", options.roles.join(","));
      if (options?.products) params.append("products", options.products.join(","));
      if (options?.locale) params.append("locale", options.locale);
      if (options?.maxpagesize) params.append("maxpagesize", options.maxpagesize.toString());
    
      const response = await fetch(`${API_BASE_URL}/courses?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Courses");
    }
    
    /**
     * Get a specific course by ID
     * GET /courses/{id}
     */
    async function getCourse(courseId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/courses/${courseId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Course");
    }
    
    /**
     * List all learning paths
     * GET /learning-paths
     */
    async function listLearningPaths(options?: {
      levels?: string[];
      roles?: string[];
      products?: string[];
      subjects?: string[];
      locale?: string;
      maxpagesize?: number;
    }): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (options?.levels) params.append("levels", options.levels.join(","));
      if (options?.roles) params.append("roles", options.roles.join(","));
      if (options?.products) params.append("products", options.products.join(","));
      if (options?.subjects) params.append("subjects", options.subjects.join(","));
      if (options?.locale) params.append("locale", options.locale);
      if (options?.maxpagesize) params.append("maxpagesize", options.maxpagesize.toString());
    
      const response = await fetch(`${API_BASE_URL}/learning-paths?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Learning Paths");
    }
    
    /**
     * Get a specific learning path by ID
     * GET /learning-paths/{id}
     */
    async function getLearningPath(learningPathId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/learning-paths/${learningPathId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Learning Path");
    }
    
    /**
     * List all modules
     * GET /modules
     */
    async function listModules(options?: {
      levels?: string[];
      roles?: string[];
      products?: string[];
      subjects?: string[];
      locale?: string;
      maxpagesize?: number;
    }): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (options?.levels) params.append("levels", options.levels.join(","));
      if (options?.roles) params.append("roles", options.roles.join(","));
      if (options?.products) params.append("products", options.products.join(","));
      if (options?.subjects) params.append("subjects", options.subjects.join(","));
      if (options?.locale) params.append("locale", options.locale);
      if (options?.maxpagesize) params.append("maxpagesize", options.maxpagesize.toString());
    
      const response = await fetch(`${API_BASE_URL}/modules?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Modules");
    }
    
    /**
     * Get a specific module by ID
     * GET /modules/{id}
     */
    async function getModule(moduleId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/modules/${moduleId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Module");
    }
    
    /**
     * Get a specific unit by ID
     * GET /units/{id}
     */
    async function getUnit(unitId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/units/${unitId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Unit");
    }
    
    // ============================================================================
    // CREDENTIALS ENDPOINTS
    // ============================================================================
    
    /**
     * List all certifications
     * GET /certifications
     */
    async function listCertifications(options?: {
      levels?: string[];
      roles?: string[];
      products?: string[];
      subjects?: string[];
      locale?: string;
      maxpagesize?: number;
    }): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (options?.levels) params.append("levels", options.levels.join(","));
      if (options?.roles) params.append("roles", options.roles.join(","));
      if (options?.products) params.append("products", options.products.join(","));
      if (options?.subjects) params.append("subjects", options.subjects.join(","));
      if (options?.locale) params.append("locale", options.locale);
      if (options?.maxpagesize) params.append("maxpagesize", options.maxpagesize.toString());
    
      const response = await fetch(`${API_BASE_URL}/certifications?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Certifications");
    }
    
    /**
     * Get a specific certification by ID
     * GET /certifications/{id}
     */
    async function getCertification(certificationId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/certifications/${certificationId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Certification");
    }
    
    /**
     * List all exams
     * GET /exams
     */
    async function listExams(options?: {
      levels?: string[];
      roles?: string[];
      products?: string[];
      locale?: string;
      maxpagesize?: number;
    }): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (options?.levels) params.append("levels", options.levels.join(","));
      if (options?.roles) params.append("roles", options.roles.join(","));
      if (options?.products) params.append("products", options.products.join(","));
      if (options?.locale) params.append("locale", options.locale);
      if (options?.maxpagesize) params.append("maxpagesize", options.maxpagesize.toString());
    
      const response = await fetch(`${API_BASE_URL}/exams?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Exams");
    }
    
    /**
     * Get a specific exam by ID
     * GET /exams/{id}
     */
    async function getExam(examId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/exams/${examId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Exam");
    }
    
    /**
     * List all applied skills
     * GET /applied-skills
     */
    async function listAppliedSkills(options?: {
      levels?: string[];
      roles?: string[];
      products?: string[];
      subjects?: string[];
      locale?: string;
      maxpagesize?: number;
    }): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (options?.levels) params.append("levels", options.levels.join(","));
      if (options?.roles) params.append("roles", options.roles.join(","));
      if (options?.products) params.append("products", options.products.join(","));
      if (options?.subjects) params.append("subjects", options.subjects.join(","));
      if (options?.locale) params.append("locale", options.locale);
      if (options?.maxpagesize) params.append("maxpagesize", options.maxpagesize.toString());
    
      const response = await fetch(`${API_BASE_URL}/applied-skills?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Applied Skills");
    }
    
    /**
     * Get a specific applied skill by ID
     * GET /applied-skills/{id}
     */
    async function getAppliedSkill(appliedSkillId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/applied-skills/${appliedSkillId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Applied Skill");
    }
    
    // ============================================================================
    // PAGINATION HELPER
    // ============================================================================
    
    /**
     * Helper to handle paginated responses
     */
    async function fetchAllPages<T>(initialUrl: string, token: string): Promise<T[]> {
      const allItems: T[] = [];
      let nextLink: string | undefined = initialUrl;
    
      while (nextLink) {
        const response = await fetch(nextLink, {
          method: "GET",
          headers: {
            "Accept": "application/json",
            "Authorization": `Bearer ${token}`
          }
        });
    
        const data = await response.json();
        allItems.push(...data.value);
        nextLink = data.nextLink;
      }
    
      return allItems;
    }
    
    // ============================================================================
    // EXAMPLE USAGE
    // ============================================================================
    
    async function main() {
      try {
        // List beginner-level certifications for Azure
        console.log("=== Listing Azure certifications (beginner level) ===");
        await listCertifications({
          levels: ["beginner"],
          products: ["azure"],
          maxpagesize: 5
        });
    
        // List certifications
        console.log("\n=== Listing certifications ===");
        await listCertifications({ maxpagesize: 5 });
    
        // List all Spanish learning paths
        console.log("\n=== Listing Spanish learning paths ===");
        await listLearningPaths({ locale: "es-es", maxpagesize: 5 });
    
        // Get a specific learning path by ID
        console.log("\n=== Getting learning path: learn.introduction-ai-azure ===");
        await getLearningPath("learn.introduction-ai-azure");
    
        // Get a specific module by ID
        console.log("\n=== Getting module: learn.wwl.fundamentals-generative-ai ===");
        await getModule("learn.wwl.fundamentals-generative-ai");
    
        // Get a specific unit by ID
        console.log("\n=== Getting unit: learn.wwl.fundamentals-generative-ai.agents ===");
        await getUnit("learn.wwl.fundamentals-generative-ai.agents");
    
        // Get a specific applied skill by ID
        console.log("\n=== Getting applied skill: applied-skill.deploy-and-configure-azure-monitor ===");
        await getAppliedSkill("applied-skill.deploy-and-configure-azure-monitor");
    
        // Get a specific certification by ID
        console.log("\n=== Getting certification: certification.d365-functional-consultant-customer-service ===");
        await getCertification("certification.d365-functional-consultant-customer-service");
    
        // Get a specific exam by ID
        console.log("\n=== Getting exam: exam.77-881 ===");
        await getExam("exam.77-881");
    
        // Get a specific instructor-led course by ID
        console.log("\n=== Getting instructor-led course: course.ai-900t00 ===");
        await getCourse("course.ai-900t00");
    
      } catch (error) {
        console.error("Error:", error);
      }
    }
    
    main();
    
    

Xác thực và chạy các ví dụ

Làm theo các bước sau để xác thực với Azure và chạy mã mẫu.

  1. Đăng nhập vào Azure CLI. Bước này sẽ mở cửa sổ trình duyệt nơi bạn nhập thông tin đăng nhập Azure của mình.

    az login
    
  2. Nếu bạn có nhiều gói đăng ký, hãy đặt gói đăng ký đang hoạt động. Thay thế <your-subscription-name> bằng tên hoặc ID đăng ký của bạn.

    az account set --subscription "<your-subscription-name>"
    
  3. Xác minh thông tin đăng nhập của bạn có thể truy cập API Nền tảng Learn.

    az account get-access-token --resource https://learn.microsoft.com
    

    Nếu thành công, bạn sẽ thấy phản hồi JSON với một accessToken trường.

  4. Chạy tệp ví dụ bằng cách sử dụng npx để thực thi tsx gói.

    npx tsx examples.ts
    
  5. (Tùy chọn) Lưu đầu ra vào tệp bằng cách sử dụng chuyển hướng đầu ra.

    npx tsx examples.ts > output.txt 2>&1
    

Dọn dẹp tài nguyên

Nếu bạn không còn cần tài nguyên được tạo trong phần bắt đầu nhanh này, bạn có thể xóa chúng.

  1. Xóa thư mục dự án và tất cả nội dung của nó.

    cd ..
    rm -rf learn-api-examples
    

    Trên Windows PowerShell, hãy sử dụng:

    cd ..
    Remove-Item -Recurse -Force learn-api-examples
    
  2. (Tùy chọn) Đăng xuất khỏi Azure CLI để xóa thông tin đăng nhập được lưu trong bộ nhớ cache.

    az logout
    

Lưu ý

Bắt đầu nhanh này không tạo bất kỳ tài nguyên Azure nào phát sinh chi phí. Các lệnh gọi API chỉ sử dụng danh tính Azure hiện có của bạn để xác thực.