其實這也不一定是在整合測試才會用到,一般會呼叫使用到外部 API 時的情境也一樣適用。
當要將一個物件的資料帶入 QueryString 時,每次就會覺得這個步驟很麻煩,甚至有一段時間是自己寫個方法來處理,但總覺得不是一個漂亮的解決方式,
於是就想到可以使用 Flurl 來處理,也的確是可以簡化以前那些繁瑣的建立 QueryString 的作法。
例如我有一個 web api 是 /api/member,為 Get 方法,並且需要帶入以下的資料才能夠取得資料
api/member?serviceId={serviceId}&webSiteId={webSiteId}&memberNo={memberNo}&memberType={memberType}
public class MemberGetParameter
{
/// <summary>
/// ServiceId (必要)
/// </summary>
[Required]
public string ServiceId { get; set; }
/// <summary>
/// WebSiteId (必要)
/// </summary>
[Required]
public string WebSiteId { get; set; }
/// <summary>
/// MemberNo (必要)
/// </summary>
[Required]
public string MemberNo { get; set; }
/// <summary>
/// 會員類別 (必要)
/// </summary>
[Required]
public MemberType MemberType { get; set; }
}
當然屬性數量少的時後是有人會默默地選擇使用自己一個一個將 Key Value 手動帶入
但是身為一個「懶惰」的程式開發人員,無法接受這樣的狀況,而且往後還會有需要帶入更多值到 QueryString 的情境,所以我就建立了這麼一個方法來處理。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
namespace Sample.Web.IntegrationTestResource.Helpers;
/// <summary>
/// class UrlUtilities.
/// </summary>
public static class UrlUtilities
{
public static QueryString ConvertToQueryString(object obj, bool enableUrlEncode = false)
{
var keyValues = from p in obj.GetType().GetProperties()
where p.GetValue(obj, null) is not null
select new KeyValuePair<string, string>
(
key: $"{p.Name}",
value: enableUrlEncode
? $"{HttpUtility.UrlEncode($"{p.GetValue(obj, null)}")}"
: p.PropertyType == typeof(DateTime)
? $"{p.GetValue(obj, null):yyyy-MM-ddTHH:mm:ss.fff}"
: $"{p.GetValue(obj, null)}"
);
var queryBuilder = new QueryBuilder(keyValues);
var queryString = queryBuilder.ToQueryString();
return queryString;
}
}
實際的使用情況如下
// arrange
var parameter = new MemberGetParameter
{
ServiceId = "wertyuioldsfghjkk",
WebSiteId = "456yuhgjbn9u8j",
MemberType = MemberType.Normal,
MemberNo = "12345678"
};
var requestUrl = string.Concat("/api/Member", UrlUtilities.ConvertToQueryString(parameter));
// act
var response = await client.GetAsync(requestUrl);
也使用了好一段時間,也沒有發生什麼太大的問題,但總覺得應該可已有更好的解決方式可以替代。
有關如何建立 QueryString 的方式有很多種,比較標準的作法都會使用到 QueryBuilder 類別,不妨可以參考以下的連結內容:
- 如何在 ASP.NET Core 漂亮的建立 Query String 查詢字串 | The Will Will Web
- HttpClient 使用 URL Parameters (Query Strings) 的方式 - Yowko's Notes
- C# - Sending query strings with HttpClient | MAKOLYTE
使用 Flurl
我所使用到的是 Fluent URL Building 的部分
看到提供的範例,應該就知道可以達到什麼樣的效果
var url = "http://www.mysite.com".SetQueryParam("x", new[] { 1, 2, 3 });
Assert.AreEqual("http://www.mysite.com?x=1&x=2&x=3", url)
所以我就把原本的程式通通改用 Flurl 來處理 Get 情境下的 QueryString 了
// arrange
var parameter = new MemberGetParameter
{
ServiceId = "wertyuioldsfghjkk",
WebSiteId = "456yuhgjbn9u8j",
MemberType = MemberType.Normal,
MemberNo = "12345678"
};
var requestUri = "/api/Member".SetQueryParams(parameter).ToUri();
// act
var response = await client.GetAsync(requestUri);
有關 Flurl 的使用,可以參考 Flurl Documentation,或是以下的兩篇文章內容
- [NET 5][NET Framework 4.8] 通過 Flurl 產生口語化的 HttpClient Request 參數 | 余小章 @ 大內殿堂 - 點部落
- 在 .NET 中使用 Flurl 高效处理Http请求 - SpringLeee - 博客园
以上
純粹是在寫興趣的,用寫程式、寫文章來抒解工作壓力