任意のJSONデータをカスタムヘッダーとともにRESTサーバーに送信する方法を教えてください。
-
22-12-2019 - |
質問
tl; DR - 認証ヘッダを使用してRESTホストにJSON文字列を送信するにはどうすればよいですか。匿名型で動作する3つの異なるアプローチを試しました。なぜ私は匿名型を使うことができないのですか?私は "group-name"という変数を設定する必要があり、ハイフンは有効なC#識別子ではありません。
背景
JSONを投稿する必要がありますが、ボディを取得できず、コンテンツタイプが正しい
関数#1 - 匿名型で動作します
コンテンツの種類とデータは正しいですが、匿名型を使用したくありません。文字列を使いたいです
static void PostData(string restURLBase, string RESTUrl, string AuthToken, string postBody)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(restURLBase);
client.DefaultRequestHeaders.Add("Auth-Token", AuthToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// StringContent content = new StringContent(postBody);
var test1 = "data1";
var test2 = "data2";
var test3 = "data3";
var response = client.PostAsJsonAsync(RESTUrl, new { test1, test2, test3}).Result; // Blocking call!
if (!response.IsSuccessStatusCode)
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
return;
}
}
.
出力#1
コンテンツの種類とデータは、AnonymouStypes + PostasjsonAsyncを使用する場合は正しいですが、匿名型を使用したくありません。
POST https://api.dynect.net/REST/Zone/ABCqqqqqqqqqqqqYYYYYtes3ss.com HTTP/1.1
Auth-Token: --- REDACTED -----
Accept: application/json
Content-Type: application/json; charset=utf-8
Host: api.dynect.net
Content-Length: 49
Expect: 100-continue
{"test1":"data1","test2":"data2","test3":"data3"}
.
関数#2 - 期待通りには機能しません
文字列を取り、それをStringContentオブジェクトに入れます。これはコンテンツタイプを変更することの副作用を持っています。
static void PostData(string restURLBase, string RESTUrl, string AuthToken, string postBody)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(restURLBase);
client.DefaultRequestHeaders.Add("Auth-Token", AuthToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
StringContent content = new StringContent(postBody);
var response = client.PostAsync(RESTUrl, content).Result; // Blocking call!
if (!response.IsSuccessStatusCode)
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
return;
}
}
.
出力#2
StringContent + PostAsync
を使用している場合、コンテンツタイプが間違っていますPOST https://api.dynect.net/REST/Zone/ABCqqqqqqqqqqqqYYYYYtes3ss.com HTTP/1.1
Auth-Token: ---- REDACTED -------
Accept: application/json // CORRECT
Content-Type: text/plain; charset=utf-8 // WRONG!!!
Host: api.dynect.net
Content-Length: 100
Expect: 100-continue
{"rdata" : ["rname" : "dynect.nfp.com", "zone" : "ABCqqqqqqqqqqqqYYYYYtes3ss.com"], "ttl" : "43200"}
// ^^ THIS IS CORRECT
.
関数#3 - 期待通りには機能しない
PostAsJsonAsync
がContentTypeを正しく設定しているため、その方法を使用できます。 (うまくいかない)
static void PostData(string restURLBase, string RESTUrl, string AuthToken, string postBody)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(restURLBase);
client.DefaultRequestHeaders.Add("Auth-Token", AuthToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
StringContent content = new StringContent(postBody);
var response = client.PostAsJsonAsync(RESTUrl, content).Result; // Blocking call!
if (!response.IsSuccessStatusCode)
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
return;
}
}
.
出力#3
コンテンツタイプは正しいです.StringContent + PostasjsonAsync
を使用すると、投稿ボディが間違っています。POST https://api.dynect.net/REST/Zone/ABCqqqqqqqqqqqqYYYYYtes3ss.com HTTP/1.1
Auth-Token: -- REDACTED ---
Accept: application/json
Content-Type: application/json; charset=utf-8
Host: api.dynect.net
Content-Length: 74
Expect: 100-continue
{"Headers":[{"Key":"Content-Type","Value":["text/plain; charset=utf-8"]}]}
.
質問
私がやりたいのは、jsonをStringとして送信すること、または実行時に定義された動的オブジェクト、HTTPコンテンツタイプが正しい、そして特別な 'auth-token'ヘッダーを持つサーバーに送信されます。
ServiceStackなどのWebAPIを使用しない場合、または他のものはクールです。
解決
/// <summary>
/// Creates a new instance of the <see cref="T:System.Net.Http.StringContent"/> class.
/// </summary>
/// <param name="content">The content used to initialize the <see cref="T:System.Net.Http.StringContent"/>.</param><param name="encoding">The encoding to use for the content.</param><param name="mediaType">The media type to use for the content.</param>
[__DynamicallyInvokable]
public StringContent(string content, Encoding encoding, string mediaType)
: base(StringContent.GetContentByteArray(content, encoding))
{
this.Headers.ContentType = new MediaTypeHeaderValue(mediaType == null ? "text/plain" : mediaType)
{
CharSet = encoding == null ? HttpContent.DefaultStringEncoding.WebName : encoding.WebName
};
}
.
StringContentのコンストラクタです。適切なエンコードとMediaType
を指定する必要があります。他のヒント
httpContentのインスタンスを直接設定することはできません。必要に応じて、サブクラスの1つを使用する必要があります。最も可能性が高いStringContent。これにより、応答、エンコード、およびコンストラクタのメディアタイプの文字列値を設定できます。 http://msdn.microsoft.com/en-us/library/system.net.http.StringContent.aspx