目次
Dataverse の WebAPI を C# で叩く系記事たちの目次です。
今回の本文
前回の続きです。
これまで CSV ファイルを読んで、テーブルに列追加を一気に行うことを考えていってみます。
■ 前回
json テキストを用意して行追加しました。
■ 今回制限
今回はまだ文字列項目しか対応できていません。 数値などその他項目は今後。
■ コード
クラス4つです。
using DataverseClientShared; using System.Net.Http.Json; using System.Text; string s = args[0]; var jsons = DataverseClientShared.CSV.Instance.ToJosnArrayFromFile(args[1]); HttpHelper http = (await HttpHelper.Instance.Init(s, new HttpClient())).Item1; foreach (var json in jsons) { var content = new StringContent(json.ToString(), Encoding.UTF8, "application/json"); var response = await http.HttpClient.PostAsync(http.Path, content); var jsonContent = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { Console.WriteLine($"Success: {response.StatusCode} {response.ReasonPhrase} {jsonContent}"); } else { Console.WriteLine($"Error: {response.StatusCode} {response.ReasonPhrase} {jsonContent}"); } }
次のクラスはこれまで毎回書いてきた定型的な部分をクラスでまとめたものです。
namespace DataverseClientShared; public class HttpHelper { public static HttpHelper Instance { get; } = new HttpHelper(); public string? Resource { get; private set; } public Uri? BaseAddress { get; private set; } public string? Path { get; private set; } public static string ClientId { get; } = "51f81489-12ee-4a9e-aaae-a2591f45987d"; public static string RedirectUri { get; } = "http://localhost"; private HttpHelper() { } public Microsoft.Identity.Client.AuthenticationResult? Token { get; private set; } public HttpClient? HttpClient { get; private set; } public HttpHelper InitPath(string fullPath) { var uri = new Uri(fullPath); Resource = uri.Scheme + "://" + uri.Host; BaseAddress = new Uri(Instance.Resource + string.Join("", uri.Segments.Take(4))); Path = new string(uri.PathAndQuery.Skip(BaseAddress.AbsolutePath.Length).ToArray()); return Instance; } public async Task<Microsoft.Identity.Client.AuthenticationResult> AuthenticateAsync() { var authBuilder = Microsoft.Identity.Client.PublicClientApplicationBuilder.Create(ClientId) .WithAuthority(Microsoft.Identity.Client.AadAuthorityAudience.AzureAdMultipleOrgs) .WithRedirectUri(RedirectUri) .Build(); string[] scopes = { Resource + "/user_impersonation" }; Microsoft.Identity.Client.AuthenticationResult token = await authBuilder.AcquireTokenInteractive(scopes).ExecuteAsync(); return Token = token; } public HttpClient SetHttpClient(HttpClient httpClient) { var client = HttpClient = httpClient ?? HttpClient ?? new HttpClient(); client.BaseAddress = BaseAddress; client.Timeout = new TimeSpan(0, 2, 0); System.Net.Http.Headers.HttpRequestHeaders headers = client.DefaultRequestHeaders; headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", Token?.AccessToken); headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); return client; } public async Task<(HttpHelper, HttpClient)> Init(string fullPath, HttpClient httpClient) { InitPath(fullPath); await AuthenticateAsync(); SetHttpClient(httpClient); return (Instance!, HttpClient!); } }
namespace DataverseClientShared; public class CSV { public static CSV Instance { get; } = new CSV(); private CSV() { } public IEnumerable<Newtonsoft.Json.Linq.JObject> ToJosnArrayFromFile(string path) { var csvString = System.IO.File.ReadAllText(path, System.Text.Encoding.UTF8); var result = ToJsonArray(csvString); return result; } public IEnumerable<Newtonsoft.Json.Linq.JObject> ToJsonArray(string csvString) { var (header, data) = CsvReader.ReadHeaderAndData(csvString); var list = new List<Newtonsoft.Json.Linq.JObject>(); foreach (var row in data) { var obj = new Newtonsoft.Json.Linq.JObject(); for (int i = 0; i < header.Length && i < row.Length; i++) { obj[RemoveTailCR(header[i])] = RemoveTailCR(row[i]); } list.Add(obj); } return list; } string RemoveTailCR(string s) => s.EndsWith("\r") ? s[..^1] : s; }
public static class CsvReader { public static string[][] Read(string csvString) => _Read(csvString); public static (string[] header, string[][] data) ReadHeaderAndData(string csvString) { var values = Read(csvString); return (values.FirstOrDefault() ?? Array.Empty<string>(), values.Skip(1).ToArray()); } private static string[][] _Read(string csvString) { List<List<List<char>>> data = new(); (bool isLineHead, bool isQuoted, char quote, bool isEscaped) = (true, false, '"', false); foreach (var c in csvString) { if (isLineHead) { data.Add(new List<List<char>>()); data.LastOrDefault()?.Add(new List<char>()); isLineHead = false; } if (data.LastOrDefault()?.LastOrDefault()?.Count == 0 && !isQuoted && (c == '"' || c == '\'')) { (isQuoted, quote, isEscaped) = (true, c, false); continue; } if (!isEscaped && isQuoted && c == quote) { isEscaped = true; continue; } if (c == ',' && (!isQuoted || isEscaped)) { data.LastOrDefault()?.Add(new List<char>()); (isQuoted, isEscaped) = (false, false); continue; } if (c == '\n' && (!isQuoted || isEscaped)) { isLineHead = true; (isQuoted, isEscaped) = (false, false); continue; } isEscaped = false; data.LastOrDefault()?.LastOrDefault()?.Add(c); } return data.Select(line => line.Select(cell => new string(cell.ToArray())).ToArray()).ToArray(); } }
難しいですね。
■ GitHub
GitHub リポジトリにコードを置いて試しています。