目次
概要
Web APIの呼び出しなどで、ベースとなるURLに対して複数のクエリパラメータ(?key=value)を付与する際、手動で文字列連結を行うと区切り文字(? や &)の管理やURLエンコードの処理が煩雑になります。 Microsoft.AspNetCore.WebUtilities パッケージに含まれる QueryHelpers クラスを使用することで、ディクショナリから自動的に正しい形式のURLを生成できます。
仕様(入出力)
- 入力: ベースURL(文字列)、追加したいパラメータのキーと値のペア(Dictionaryなど)。
- 出力: クエリパラメータが正しく結合され、エンコードされた完全なURL文字列。
- 前提:
.NET Standard 2.0以上。外部パッケージMicrosoft.AspNetCore.WebUtilitiesが必要。
基本の使い方
まず、NuGetパッケージを追加します。
dotnet add package Microsoft.AspNetCore.WebUtilities
ディクショナリを渡すだけで、自動的に ? や & を付与し、値をエンコードして結合します。
var params = new Dictionary<string, string?>
{
["city"] = "Tokyo",
["q"] = "C# & .NET" // 自動でエンコードされます
};
// https://example.com/api?city=Tokyo&q=C%23%20%26%20.NET
var url = QueryHelpers.AddQueryString("https://example.com/api", params);
コード全文
ここでは「天気予報API」に対して、都市名、取得日数、APIキーなどのパラメータを動的に構築するシミュレーションを行います。
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.WebUtilities;
public class Program
{
public static void Main()
{
// ベースとなるAPIのエンドポイント
const string BaseUrl = "https://api.weather-service.com/v1/forecast";
// パラメータの準備
// 値にスペースや記号が含まれていても、自動的にURLエンコードされます
var queryParams = new Dictionary<string, string?>
{
["location"] = "New York", // スペースを含む値
["days"] = "7", // 数値も文字列として渡す
["unit"] = "metric", // 単位
["appid"] = "Key_12345!@#", // 記号を含むAPIキー
["lang"] = null // nullの値(後述の注意点参照)
};
Console.WriteLine("--- URL生成開始 ---");
// クエリ文字列の組み立て
// AddQueryStringは、既存のURLにクエリがあるか判定し、適切に '?' または '&' で結合します
string requestUrl = QueryHelpers.AddQueryString(BaseUrl, queryParams);
Console.WriteLine("生成されたURL:");
Console.WriteLine(requestUrl);
// --- 確認用: 生成されたURLの検証 ---
Console.WriteLine("\n[検証]");
// "New York" が "New%20York" になっているか確認
if (requestUrl.Contains("New%20York"))
{
Console.WriteLine("判定: スペースが正しくエンコードされています。");
}
// "Key_12345!@#" が適切に処理されているか
// ! や @ など一部の記号はRFC標準によりそのまま残る場合がありますが、
// # はフラグメントと混同するためエンコード(%23)されるべきです
if (requestUrl.Contains("%23"))
{
Console.WriteLine("判定: 特殊記号(#)が正しくエンコードされています。");
}
}
}
実行結果例
--- URL生成開始 ---
生成されたURL:
https://api.weather-service.com/v1/forecast?location=New%20York&days=7&unit=metric&appid=Key_12345!%40%23&lang=
[検証]
判定: スペースが正しくエンコードされています。
判定: 特殊記号(#)が正しくエンコードされています。
カスタムポイント
- null値の除外: デフォルトでは値が
nullの場合、空文字としてキーだけ(例:&lang=)追加されるか、空文字が設定されます(バージョンによる)。値がnullのパラメータをURLに含めたくない場合は、Dictionaryを作成する段階でWhereなどを使ってフィルタリングしてください。 - 単一パラメータの追加: Dictionaryを使わず、
QueryHelpers.AddQueryString(url, "key", "value")を使えば、パラメータを1つだけ追加できます。メソッドチェーンで繋ぐことも可能です。 - コレクションの扱い: 同じキーで複数の値を渡したい場合(例:
?id=1&id=2)、値の型としてMicrosoft.Extensions.Primitives.StringValuesを使用するか、ライブラリの仕様に合わせて工夫が必要です。
注意点
- 依存関係: この機能は標準ライブラリ(System.Net等)ではなく、ASP.NET Core向けのライブラリに含まれています。コンソールアプリやWPFで使用する場合は必ずNuGetパッケージのインストールが必要です。
- エンコード仕様: 内部的に
Uri.EscapeDataString相当の処理が行われますが、ブラウザやサーバーの仕様によっては挙動の差異に注意が必要です。 - 既存パラメータの結合: ベースURLに既に
?id=1のようなクエリが含まれている場合でも、QueryHelpersはそれを検知して正しく&で後続パラメータを繋いでくれます。
応用
Nullを除外してクリーンなURLを作る
値が存在しない(nullまたは空文字)パラメータを自動的に除外する拡張メソッド風の実装例です。
var parameters = new Dictionary<string, string?>
{
["id"] = "101",
["filter"] = null, // これは除外したい
["sort"] = "" // これも除外したい
};
// 値があるものだけを抽出してDictionary化
var validParams = parameters
.Where(kv => !string.IsNullOrEmpty(kv.Value))
.ToDictionary(kv => kv.Key, kv => kv.Value);
var cleanUrl = QueryHelpers.AddQueryString("https://example.com", validParams);
// 結果: https://example.com?id=101
まとめ
null 値の扱いに注意し、必要に応じて事前にフィルタリングを行ってください。
QueryHelpers.AddQueryString を使うことで、面倒なURLエンコードや区切り文字の結合処理を委譲できます。
Web APIクライアントの実装において、可読性と安全性を高めるために非常に有用です。
