Lập trình C# (C Sharp)

Lớp HttpClient được sử dụng để gửi truy vấn HTTP và nhận phản hồi (response) từ các truy vấn đó. Lớp này thuộc namespace System.Net.Http, namespace này chứa các lớp giúp tạo ra sự liên lạc giữa client và server. Để làm việc với HttpClient dùng những namespace sau:

using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using System.Text;

Tạo truy vấn GET bất đồng bộ với HttpClient

Để tạo ra truy vấn GET tới một địa chỉ URL, thực hiện phương thức GetAsync(url), đây là phương thức async khi kết thúc nó trả về đối tượng HttpResponseMessage từ đối tượng này ta sẽ biết kết quả truy vấn, và ta có thể đọc được dữ liệu tải về.

var httpClient = new  HttpClient();
HttpResponseMessage response = await httpClient.GetAsync(url);

Nếu muốn thiết lập các Header gửi đi, trước khi gọi GetAssync thì thêm các Header như sau, ví dụ thêm 1 header tên là Accept:

httpClient.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml+json");

Khi có đối tượng lớp HttpResponseMessage có thể thực hiện các tác vụ đọc dữ liệu, tham khảo một số thuộc tính và phương thức:

EnsureSuccessStatusCode(); Đảm bảo, phát sinh Exception nếu truy vấn không thành công - nêu không gọi hàm này, nếu truy vấn không thành công, ví dụ server lỗi - nó sẽ không phát sinh Exception
IsSuccessStatusCode Thuộc tính nếu true có biết mã trả về thành công, ví dụ mã trạng thái 200
StatusCode Thuộc tính có kiểu enum HttpStatusCode cho biết mã trạng thái của kết quả, để chuyển sang số nguyên (int)HttpStatusCode
ReasonPhrase Đoạn text, mô tả thông tin cho mã trạng thái như OK khi mã trạng thái là 200
Headers Thuộc tính kiểu HttpResponseHeaders chứa các Header trả về, mỗi phần trong nó là chứa tên header và các giá trị cho tên header đó. Có thể đọc các Header trả về, ví dụ:
HttpHeaders headers = respone.Headers;                  // Lấy các Headers  trả về
foreach (var header in headers)
{
    string key_header                = header.Key;      // Key, ví dụ: Cache-Control, Set-Cookie ...
    IEnumerable<string> value_header = header.Value;    // Danh sách các giá trị cho header
}
Content Thuộc tính kiểu HttpContent, từ đối tượng này ta lấy được nội dung (body) của truy vấn trả về. Để đọc nó, có một số phương thức mà ta sẽ áp dụng cho các ví dụ ngay sau đây gồm:
  • ReadAsStringAsync đọc nội dung (content) HTTP trả về chuỗi (có encoding). Đối với phương thức này, một số server trả về mã CharSet mà .NET Core không nhận ra sẽ gây lỗi, để encoding được cho trường hợp này thì trước khi thi hành thiết lập cho nó:
    Content.Headers.ContentType.CharSet = @"utf-8"; //ISO-8859-1
  • ReadAsStreamAsync trả về đối tượng Stream, từ stream dùng kỹ thuật đọc luồng để đọc nội dung: xem thêm Đọc streams Dữ liệu đọc được là các byte, bạn có thể lưu chúng ra file hoặc convert thành chuỗi
  • ReadAsByteArrayAsync đọc trả về mảng byte, từ mảng byte này có thể lưu nó ra file. Hoặc encoding nó thành chuỗi, ví dụ encoding utf-8
    string content = System.Text.Encoding.UTF8.GetString(byteArray);

Ví dụ, tạo truy vấn GET, tải về trang Web

Source Code
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace HttpClientExample
{

    class Program
    {
        // Chức năng in thông tin Header
        public static void ShowHeaders(HttpHeaders headers)
        {
            Console.WriteLine("Các Header:");
            foreach (var header in headers)
            {
                string value = string.Join(" ", header.Value);              //  Nối các giá trị header lại
                Console.WriteLine($"{header.Key,20} : {value}");
             }
            Console.WriteLine();
         }


        public static async Task<string> GetWebContent(string url)
        {
            using (var httpClient = new  HttpClient())
            {
                Console.WriteLine($"Starting connect {url}");
                try {
                    httpClient.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml+json");
                    HttpResponseMessage response = await httpClient.GetAsync(url);
                    response.EnsureSuccessStatusCode();
                    if (response.IsSuccessStatusCode)
                    {
                        Console.WriteLine($"Tải thành công - statusCode {(int)response.StatusCode} {response.ReasonPhrase}");
                        ShowHeaders(response.Headers);
                        Console.WriteLine("Starting read data");

                        response.Content.Headers.ContentType.CharSet = @"ISO-8859-1"; // có thể bỏ dòng này

                        string htmltext = await response.Content.ReadAsStringAsync();
                        Console.WriteLine($"Received payload of {htmltext.Length} characters");
                        Console.WriteLine();
                        return htmltext;
                    }
                    else
                    {
                        Console.WriteLine($"Lỗi - statusCode {response.StatusCode} {response.ReasonPhrase}");
                        return null;
                    }
                } catch (Exception e) {
                    Console.WriteLine(e.Message);
                    return null;
                }
            }
        }
        static void Main(string[] args)
        {
            var htmltask = GetWebContent("https://google.com.vn");

            htmltask.Wait();                    // cho hoàn thành tác vụ
            var html = htmltask.Result;         // đọc chuỗi trả về (content)
            Console.WriteLine(html!=null ? html.Substring(0, 150): "Lỗi");
        }
    }
}

ReadAsStreamAsync và ReadAsByteArrayAsync đọc nội dung

Ở ví dụ trên, đã dùng ReadAsStringAsync để đọc content convert về chuỗi. Ngoài ra, cũng có thể sử dụng ReadAsStreamAsync để tạo stream để đọc kết quả, sử dụng ReadAsByteArrayAsync để đọc hết các byte trả về mảng byte.

Source Code

using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.IO;

namespace HttpClientExample
{
    public class ViduHttpClient {
        HttpClient _httpClient = null;
        public HttpClient httpClient => _httpClient ?? (new HttpClient());

        public async Task<byte[]> DownloadDataBytes(string url)
        {
            Console.WriteLine($"Starting connect {url}");
            try {
                HttpResponseMessage response = await httpClient.GetAsync(url);
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsByteArrayAsync();
            } catch (Exception e) {
                Console.WriteLine(e.Message);
                throw e;
            }
        }

        public async Task<Stream> DownloadDataStream(string url)
        {
            Console.WriteLine($"Starting connect {url}");
            try {
                HttpResponseMessage response = await httpClient.GetAsync(url);
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStreamAsync();
            } catch (Exception e) {
                Console.WriteLine(e.Message);
                throw e;
            }
        }
    }

class Program {

    static void Main(string[] args)
    {
        var httpclient = new ViduHttpClient();

        // Đọc dữ liệu - trả về mảng byte[]
        // Ví dụ, tải một ảnh - lưu ra file  anh1.png
        var url1    = "https://raw.githubusercontent.com/xuanthulabnet/jekyll-example/master/images/jekyll-01.png";
        var task1   = httpclient.DownloadDataBytes(url1);
        task1.Wait();                       // chờ cho tải xong
        byte[] dataimg = task1.Result;
        string filepath = "anh1.png";
        using (var stream = new FileStream(filepath, FileMode.Create, FileAccess.Write, FileShare.None))
        {
            stream.Write(dataimg, 0, dataimg.Length);
        }

        //Đọc dữ liệu - trả về stream
        // Ví dụ, tải một ảnh - lưu ra file  anh2.png
        string url2     = "https://raw.githubusercontent.com/xuanthulabnet/linux-centos/master/docs/samba1.png";
        var task2       = httpclient.DownloadDataStream(url2);
        int SIZEBUFFER  = 500;
        string filepath2 = "anh2.png";
        using (var streamwrite = File.OpenWrite(filepath2))
        using (var streamread = task2.Result)
        {
            byte[] buffer = new byte[SIZEBUFFER];   // tạo bộ nhớ đệm lưu dữ liệu khi đọc stream
            bool endread = false;
            do
            {
                int numberRead = streamread.Read(buffer, 0, SIZEBUFFER);
                if (numberRead == 0) endread = true;
                else {
                    streamwrite.Write(buffer, 0, numberRead);
                }

            } while (!endread);

        }
    }
}
}

Tạo request với SendAsync

Ngoài phương thức GetAsync gửi Request với phương thức GET ở trên ra, có thể dùng phương thức SendAsync

Phương thức này có tham số kiểu HttpRequestMessage, giúp chúng ta tùy biến, thêm được nhiều thông tin khi gửi request hơn. Ví dụ tạo Request:

var request = new HttpRequestMessage(HttpMethod.Post, url);

Như vậy, có thể thiết lập phương thức GET, POST, DELETE ... khi tạo truy vấn.

Ví dụ sau, sử dụng SendAsync gửi HTTP POST, gửi nội dung JSON đến một URL. (Đây là cách tạo truy vấn đến các Webservice API)

using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using System.Text;
namespace HttpClientExample
{
    public class ViduHttpClient {
        HttpClient _httpClient = null;
        public HttpClient httpClient => _httpClient ?? (new HttpClient());

        public async Task<string> SendAsyncJson(string url, string json)
        {
            Console.WriteLine($"Starting connect {url}");
            try {

                var request = new HttpRequestMessage(HttpMethod.Post, url);
                HttpContent httpContent = new StringContent(json, Encoding.UTF8, "application/json");
                request.Content = httpContent;
                var response = await httpClient.SendAsync(request);
                var rcontent = await response.Content.ReadAsStringAsync();
                return rcontent;

            } catch (Exception e) {
                Console.WriteLine(e.Message);
                throw e;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var url = "https://domain.com/";
            var json =@"
                {
                    ""thamso1"":""giatri1"",
                    ""thamso2"":""giatrr2"",
                }";
           ViduHttpClient vidu = new ViduHttpClient();
           var task = vidu.SendAsyncJson(url, json);
           task.Wait();
           Console.WriteLine(task.Result);
        }
    }
}
Đăng ký theo dõi ủng hộ kênh