.NET 10

[C#] Server 與 Client 全程走 MessagePack:一個 .NET 10 Web API 的實作紀錄

本文示範如何在 .NET 10 環境下使用 MessagePack 實作從 Client 到 Server 的完整二進位傳輸流程,包含模型定義、API 控制器實作及客戶端呼叫範例,適用於追求高效能的內部系統溝通。

[C#] Server 與 Client 全程走 MessagePack:一個 .NET 10 Web API 的實作紀錄

很多人聽過 MessagePack,但真正用在 Web API 上的機會其實不多,尤其是完整從 Client 到 Server 都走 binary 傳輸的情境

這篇文章用 .NET 10 示範一個最小可行的案例,實作一個只接受 MessagePack 的 Web API,並搭配一個 Client 呼叫範例

讓整個傳輸流程從頭到尾都清楚可以快速複製貼上了解 

1. 我測試環境是 .NET 10 ,一樣沒有內建,請先到 nuget 下面去下載 https://www.nuget.org/packages/messagepack

2. 建立模型,記得 Server and Client 的模型要一模一樣,包括 Key(index) 不然會出錯,這點要特別注意

在設計實務上,建議使用另一個專統一描述模型不要用兩邊各自為政的資料模型,這樣比較安全,也不用重複撰寫


    
    

       [MessagePackObject]
       public sealed class User

       {

           [Key(0)] public int Id { get; set; }
           [Key(1)] public string Name { get; set; } = "";
           [Key(2)] public List Friends { get; set; } = new();
           [Key(3)] public int Age { get; set; }
           [Key(4)] public string Alias { get; set; } = "";
           [Key(5)] public decimal Salary { get; set; }
           [Key(6)] public DateTime Birth { get; set; }

       }

    


  

3. Server side 的程式碼,這邊我直接開一個 Web API 專案然後直接加上一個 Controller ,這樣你也不用去調整其他設定

如果你是自己開一個空白的專案,記得在 Program.cs 要加入    app.MapControllers(); 

這邊我很常忘記,我提醒自己一下,這邊我就修改進來的MessagePack 還原成物件,並且修改一些資料

C# Code 


  
[ApiController]

   [Route("api/user")]

   public class UserController : ControllerBase

   {

       [HttpPost("edit")]

       public async Task EditUser()

       {

           // 1. 讀取 request body binary data

           using var ms = new MemoryStream();

           await Request.Body.CopyToAsync(ms);

           var requestBytes = ms.ToArray();



           // 2. MessagePack 反序列化

           var user = MessagePackSerializer.Deserialize(

               requestBytes,

               MessagePackSerializerOptions.Standard

           );



           // 3. 模擬處理

           user.Name = user.Name + " --Server 改過了";

           user.Age += 1;



           // 4. 序列化回傳

           var responseBytes = MessagePackSerializer.Serialize(

               user,

               MessagePackSerializerOptions.Standard

           );



           return File(

               responseBytes,

               "application/x-msgpack"

           );

       }

   }

   
   

   

  


4. 接下來是 Client 呼叫的部分,這邊的部分我就製作一個 User 資料序列化成 MessagePack 後就傳給 Server 

並且拿到回應後用 JSON  印出看看是不是得到預期答案


 

   

            var handler = new HttpClientHandler

            {

                ServerCertificateCustomValidationCallback =

                    HttpClientHandler.DangerousAcceptAnyServerCertificateValidator

            };



            var client = new HttpClient(handler);



            var user = new User

            {

                Id = 1,

                Name = "許當麻測試",

                Age = 42,

                Birth=new DateTime(1981,1,1),

                Alias="測試"

            };



            // 1. Serialize to MessagePack

            byte[] requestBytes = MessagePackSerializer.Serialize(

                user,

                MessagePackSerializerOptions.Standard

            );



            // 2. 建立 HttpContent

            var content = new ByteArrayContent(requestBytes);

            content.Headers.ContentType =

                new MediaTypeHeaderValue("application/x-msgpack");



            // 3. 呼叫 Server

            var response = await client.PostAsync(

                   "http://localhost:5260/api/user/edit",

                   content

               );



       

            response.EnsureSuccessStatusCode();



            // 4. 讀取 binary response

            var responseBytes = await response.Content.ReadAsByteArrayAsync();



            // 5. Deserialize

            var responseUser = MessagePackSerializer.Deserialize(

                responseBytes,

                MessagePackSerializerOptions.Standard

            );



            Console.WriteLine(

                "Result:" + JsonConvert.SerializeObject(responseUser)

            );





   

   

  


執行結果:


 

    Result:{"Id":1,"Name":"許當麻測試 --Server 改過了","Friends":[],"Age":43,"Alias":"測試","Salary":0.0,"Birth":"1981-01-01T00:00:00Z"}

    

  

來個結論,如果你是對外的專案當然就是以 JSON 為主,如果你是在 server 跟 server 之間的溝通

都是在自己可以控制的範圍,MessagePack 的確是一個好選擇,中間傳遞資料小了,還原速度也可以更快速

我個人在兩台自己的機器溝通的時候的確是採用這方案, 畢竟都是自己專案的機器一切都是好說話。