Sử dụng AJAX trong Ứng dụng ASP.NET

Việc tích hợp khả năng không đồng bộ (Asynchronous JavaScript and XML - AJAX) vào các ứng dụng web là một kỹ thuật tiêu chuẩn để nâng cao trải nghiệm người dùng, cho phép cập nhật nội dung trang mà không cần tải lại toàn bộ. Trong bối cảnh phát triển web với ASP.NET, có nhiều phương pháp để triển khai AJAX, trong đó hai cách tiếp cận phổ biến nhất là sử dụng thư viện jQuery với phương thức $.ajax() mạnh mẽ, và sử dụng các tính năng AJAX được tích hợp sẵn của .NET thông qua ScriptManager.

AJAX với jQuery và Yêu cầu GET tới Trang Thông thường

Phương thức $.ajax() của jQuery cung cấp một cách linh hoạt để gửi các yêu cầu HTTP. Cấu trúc cơ bản thường là $.ajax({ cài đặt }), với một số tùy chọn quan trọng sau:

  • type: Phương thức HTTP (ví dụ: 'GET', 'POST').
  • url: Đường dẫn tài nguyên đích.
  • async: Xác định yêu cầu là không đồng bộ (mặc định là true).
  • data: Dữ liệu gửi đi cùng yêu cầu.
  • dataType: Định dạng dữ liệu dự kiến từ máy chủ (ví dụ: 'json', 'xml', 'text').
  • success: Hàm callback được gọi khi yêu cầu thành công.
  • error: Hàm callback được gọi khi yêu cầu thất bại.

Hãy xem xét một ví dụ đơn giản. Chúng ta sẽ tạo một ứng dụng web ASP.NET cơ bản, thêm thư viện jQuery và hai trang: TrangChinh.aspx để hiển thị giao diện người dùng và DuLieuDonGian.aspx làm trang xử lý yêu cầu.

TrangChinh.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TrangChinh.aspx.cs" Inherits="WebProject.TrangChinh" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title>Demo AJAX</title>
    <script src="Scripts/jquery-3.6.0.min.js" type="text/javascript"></script>
    <style type="text/css">
        body { font-family: Arial, sans-serif; margin: 20px; }
        #outputArea {
            margin-top: 20px; padding: 15px;
            min-height: 100px; width: 400px;
            background-color: #f0f0f0; border: 1px dashed #ccc;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
        <h2>Kiểm tra AJAX với jQuery</h2>
        <input type="button" value="Gửi Yêu cầu GET Đơn giản" onclick="guiYeuCauGet()" />
        <div id="outputArea">
            <p>Kết quả sẽ hiển thị ở đây:</p>
        </div>

        <script type="text/javascript">
            function hienThiKetQua(text) {
                document.getElementById("outputArea").innerHTML += ('<br/>' + text);
            }

            function guiYeuCauGet() {
                $.ajax({
                    type: 'GET',
                    url: 'DuLieuDonGian.aspx',
                    async: true,
                    success: function (phanHoi) {
                        alert("Nội dung từ máy chủ: \n" + phanHoi);
                    },
                    error: function () {
                        hienThiKetQua('LỖI: Không thể lấy dữ liệu!');
                    }
                });
            }
        </script>
    </form>
</body>
</html>

DuLieuDonGian.aspx

Ban đầu, trang này không cần xử lý gì đặc biệt. Khi yêu cầu thành công, một hộp thoại sẽ hiện ra chứa toàn bộ nội dung HTML của DuLieuDonGian.aspx.

Tuy nhiên, mục tiêu chính của AJAX không phải là tải toàn bộ trang HTML. Thay vào đó, chúng ta muốn nhận về các phần dữ liệu cụ thể để cập nhật các thành phần trên trang mà không gây ra tải lại toàn bộ trang. Điều này đòi hỏi chúng ta phải gọi các phương thức cụ thể trên máy chủ và nhận về dữ liệu có cấu trúc.

Yêu cầu GET với jQuery để Gọi Phương thức Cụ thể trên Máy chủ

Để chỉ lấy dữ liệu cần thiết, chúng ta cần sửa đổi DuLieuDonGian.aspx để nó có thể xử lý các tham số được gửi đến và trả về phản hồi tùy chỉnh. Cần lưu ý là phương pháp này không phải là cách tiếp cận chuyên nghiệp nhất, nhưng nó minh họa cách cơ bản để chuyển dữ liệu và gọi logic máy chủ.

DuLieuDonGian.aspx.cs

using System;
using System.Web.UI;

namespace WebProject
{
    public partial class DuLieuDonGian : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            string hanhDong = Request.QueryString["action"];
            Response.Clear(); // Xóa mọi nội dung phản hồi đã có

            if (!string.IsNullOrEmpty(hanhDong))
            {
                switch (hanhDong)
                {
                    case "layThoiGian":
                        Response.Write(LayThoiGianHienTai());
                        break;
                    case "layNgay":
                        Response.Write(LayNgayHienTai());
                        break;
                    default:
                        Response.Write("Hành động không hợp lệ.");
                        break;
                }
            }
            else
            {
                Response.Write("Chưa có hành động nào được chỉ định.");
            }
            Response.End(); // Kết thúc quá trình phản hồi, chỉ gửi nội dung đã viết
        }

        private string LayNgayHienTai()
        {
            return DateTime.Now.ToShortDateString();
        }

        private string LayThoiGianHienTai()
        {
            return DateTime.Now.ToShortTimeString();
        }
    }
}

Tiếp theo, chúng ta sẽ cập nhật TrangChinh.aspx để gọi các phương thức này, thêm một hàm JavaScript mới:

TrangChinh.aspx (thêm hàm JavaScript)

function guiYeuCauGet_DuLieu() {
    $.ajax({
        type: 'GET',
        url: 'DuLieuDonGian.aspx',
        async: true,
        data: { action: 'layThoiGian' }, // Gửi tham số action
        success: function (ketQua) {
            hienThiKetQua('Thời gian hiện tại: ' + ketQua);
        },
        error: function () {
            hienThiKetQua('LỖI: Không thể lấy thời gian!');
        }
    });
}

Bạn có thể thay đổi nút bấm để gọi guiYeuCauGet_DuLieu(). jQuery sẽ tự động chuyển đối tượng data thành các tham số trong URL cho yêu cầu GET (ví dụ: DuLieuDonGian.aspx?action=layThoiGian).

Yêu cầu POST với jQuery và Dữ liệu JSON (Sử dụng HTTP Handler)

Cách tiếp cận trên có vẻ nghiệp dư vì phải xử lý thủ công trong Page_Load. Một giải pháp chuyên nghiệp và nhẹ hơn là sử dụng HTTP Handler (ASHX). HTTP Handler cho phép chúng ta xử lý yêu cầu HTTP mà không đi qua toàn bộ vòng đời của một trang ASP.NET, giúp hiệu suất tốt hơn cho các yêu cầu AJAX đơn giản. Để tương tác với dữ liệu có cấu trúc như JSON, chúng ta sẽ sử dụng thư viện Json.NET.

Đầu tiên, thêm một tệp "Generic Handler" mới vào dự án, ví dụ XuLyDuLieu.ashx. Cài đặt NuGet package Newtonsoft.Json.

DoiTuongMau.cs

using System;

namespace WebProject
{
    public class DoiTuongMau
    {
        public int MaSo { get; set; }
        public string Ten { get; set; }
        public string MoTa { get; set; }
    }
}

XuLyDuLieu.ashx.cs

using System;
using System.Web;
using Newtonsoft.Json;

namespace WebProject
{
    public class XuLyDuLieu : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "application/json"; // Đặt Content-Type là JSON

            string maSoStr = context.Request.Form["MaSo"];
            int maSo = 0;
            if (!string.IsNullOrEmpty(maSoStr) && int.TryParse(maSoStr, out maSo))
            {
                DoiTuongMau doiTuong;
                if (maSo == 101)
                {
                    doiTuong = new DoiTuongMau { MaSo = 101, Ten = "Sản phẩm A", MoTa = "Mô tả sản phẩm A" };
                }
                else
                {
                    doiTuong = new DoiTuongMau { MaSo = maSo, Ten = "Sản phẩm khác", MoTa = "Không tìm thấy chi tiết" };
                }
                string jsonString = JsonConvert.SerializeObject(doiTuong);
                context.Response.Write(jsonString);
            }
            else
            {
                context.Response.Write(JsonConvert.SerializeObject(new { error = "Mã số không hợp lệ" }));
            }
        }

        public bool IsReusable
        {
            get { return false; }
        }
    }
}

Tiếp theo, chúng ta sẽ tạo hàm JavaScript để gửi yêu cầu POST tới Handler này:

TrangChinh.aspx (thêm hàm JavaScript)

function guiYeuCauPost_JSON() {
    $.ajax({
        type: 'POST',
        url: 'XuLyDuLieu.ashx',
        async: true,
        data: { MaSo: '101' }, // Gửi dữ liệu POST
        success: function (ketQua) {
            hienThiKetQua('Dữ liệu JSON thô: ' + ketQua);
            // Parse chuỗi JSON thành đối tượng JavaScript
            var obj = JSON.parse(ketQua); 
            hienThiKetQua('Mã số: ' + obj.MaSo);
            hienThiKetQua('Tên: ' + obj.Ten);
            hienThiKetQua('Mô tả: ' + obj.MoTa);
        },
        error: function () {
            hienThiKetQua('LỖI: Không thể gửi yêu cầu POST!');
        }
    });
}

Với cách này, chúng ta nhận về một chuỗi JSON từ máy chủ và sau đó phân tích nó thành một đối tượng JavaScript để sử dụng.

WebService và ScriptManager

Microsoft cung cấp giải pháp tích hợp cho AJAX thông qua WebService và ScriptManager. WebService cho phép bạn định nghĩa các phương thức trên máy chủ có thể được gọi từ phía client thông qua JavaScript, và ScriptManager giúp tự động tạo proxy JavaScript cho các WebService này.

Thêm một WebService mới vào dự án (ví dụ: DichVuDuLieu.asmx).

DichVuDuLieu.asmx.cs

using System;
using System.Web.Services;
using System.Web.Script.Services;

namespace WebProject
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // Kích hoạt WebService để có thể gọi từ script
    [ScriptService] 
    public class DichVuDuLieu : WebService
    {
        [WebMethod]
        public DoiTuongMau LayThongTinDoiTuong(int idDoiTuong)
        {
            if (idDoiTuong == 1)
            {
                return new DoiTuongMau { MaSo = 1, Ten = "Vật phẩm X", MoTa = "Chi tiết vật phẩm X" };
            }
            else
            {
                return new DoiTuongMau { MaSo = idDoiTuong, Ten = "Vật phẩm Y", MoTa = "Chi tiết vật phẩm Y" };
            }
        }

        [WebMethod]
        public string LayNgayThang(bool dinhDangDai)
        {
            if (dinhDangDai)
            {
                return DateTime.Now.ToLongDateString();
            }
            else
            {
                return DateTime.Now.ToShortDateString();
            }
        }
    }
}

Lưu ý thuộc tính [ScriptService] là rất quan trọng để WebService có thể được gọi từ client script. Sau đó, trong TrangChinh.aspx, thêm ScriptManager và tham chiếu đến WebService của chúng ta:

TrangChinh.aspx (thêm ScriptManager)

<form id="form1" runat="server">
    <asp:ScriptManager ID="scriptManagerMain" runat="server">
        <Services>
            <asp:ServiceReference Path="~/DichVuDuLieu.asmx" />
        </Services>
    </asp:ScriptManager>
    
    <!-- Các nội dung và nút bấm khác -->
    <input type="button" value="Gọi WebService (ScriptManager)" onclick="goiWebService()" />
    <div id="outputArea">
        <p>Kết quả sẽ hiển thị ở đây:</p>
    </div>
    
    <script type="text/javascript">
        // ... hàm hienThiKetQua ...

        function goiWebService() {
            // Gọi phương thức WebService thông qua proxy tự động của ScriptManager
            WebProject.DichVuDuLieu.LayThongTinDoiTuong(1, function (ketQua) {
                hienThiKetQua('Thông tin đối tượng - Mã số: ' + ketQua.MaSo);
                hienThiKetQua('Thông tin đối tượng - Tên: ' + ketQua.Ten);
            }, function (loi) {
                hienThiKetQua('LỖI từ WebService: ' + loi.get_message());
            });
        }
    </script>
</form>

Một lợi ích lớn của việc sử dụng ScriptManager với WebService là các đối tượng .NET được trả về (như DoiTuongMau) sẽ tự động được tuần tự hóa thành đối tượng JSON trên client, giúp chúng ta có thể truy cập các thuộc tính trực tiếp mà không cần phân tích cú pháp JSON thủ công.

Kết hợp jQuery và WebService

Mặc dù ScriptManager tiện lợi, nó có thể hạn chế về tính linh hoạt so với jQuery. Để có được cả hai ưu điểm - sự linh hoạt của jQuery và khả năng tổ chức mã tốt của WebService với nhiều phương thức - chúng ta có thể sử dụng jQuery để gọi trực tiếp các phương thức của WebService.

TrangChinh.aspx (thêm hàm JavaScript)

function goiWebService_jQuery() {
    $.ajax({
        type: 'POST', // WebService ASP.NET thường yêu cầu POST
        url: 'DichVuDuLieu.asmx/LayNgayThang', // Đường dẫn WebService + tên phương thức
        data: JSON.stringify({ dinhDangDai: true }), // Gửi đối tượng JSON
        contentType: 'application/json; charset=utf-8', // Quan trọng cho WebService
        dataType: 'json', // Mong đợi phản hồi JSON
        success: function (phanHoi) {
            // WebService trả về đối tượng { d: "..." }
            hienThiKetQua('Ngày tháng (dùng jQuery): ' + phanHoi.d);
        },
        error: function (xhr, status, error) {
            hienThiKetQua('LỖI khi gọi WebService bằng jQuery: ' + error);
        }
    });
}

Khi gọi WebService ASP.NET bằng jQuery, có một vài điểm cần lưu ý:

  • Phương thức HTTP phải là POST.
  • url phải bao gồm cả tên WebService và tên phương thức (ví dụ: DichVuDuLieu.asmx/LayNgayThang).
  • Dữ liệu gửi đi trong data cần được chuyển đổi thành chuỗi JSON bằng JSON.stringify().
  • contentType phải được đặt là application/json; charset=utf-8.
  • WebService ASP.NET mặc định bọc kết quả trả về trong một đối tượng có thuộc tính d (ví dụ: {"d":"Thứ Tư, 29 tháng 5 năm 2024"}), vì vậy bạn cần truy cập kết quả qua phanHoi.d.

Cách tiếp cận này mang lại sự cân bằng tốt giữa tính linh hoạt của jQuery và khả năng quản lý các phương thức trên máy chủ của WebService.

Thẻ: asp.net ajax jQuery ScriptManager webservice

Đăng vào ngày 20 tháng 7 lúc 09:10