Come posso inviare dati arbitrari JSON, con un'intestazione personalizzata, a un server di riposo?
-
22-12-2019 - |
Domanda
TL; DR - Come faccio a inviare una stringa JSON a un host di riposo con un colpo di testa? Ho provato 3 approcci diversi trovati che funziona con tipi anonimi. Perché non posso usare tipi anonimi? Ho bisogno di impostare una variabile chiamata "nome di gruppo" e un trattino non è un identificatore C # valido.
Sfondo
Ho bisogno di pubblicare JSON ma non è in grado di ottenere il corpo e il tipo di contenuto corretto
Funzione # 1 - Funziona con tipi anonimi
Il tipo di contenuto e i dati sono corretti, ma non voglio usare tipi anonimi. Voglio usare una stringa
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;
}
}
.
Uscita # 1
Tipo di contenuto e dati sono corretti quando si utilizzano anonymoustypes + PostensjsAsync, ma non voglio usare tipi anonimi.
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"}
.
Funzione # 2 - non funziona come previsto
Prendi una stringa e mettilo in un oggetto StringContent. Questo ha un effetto collaterale di modificare il tipo di contenuto.
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;
}
}
.
Uscita # 2
Il tipo di contenuto è errato quando si utilizza 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
.
Funzione # 3 - Non funziona come previsto
Dal momento che conosco PostAsJsonAsync
Imposta correttamente il contentType, consente di utilizzare quel metodo. (non funziona)
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;
}
}
.
output # 3
Il tipo di contenuto è corretto, il post corpo è sbagliato quando si utilizza StringContent + PostaSjsAsync
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"]}]}
.
Domanda
Tutto quello che voglio fare è inviare JSON come stringa, o oggetto dinamico definito in fase di runtime, a un server, con il tipo di contenuto HTTP corretto e con un'intestazione speciale 'AUTH-TOKEN'.
Qualsiasi esempio, se non si utilizza Webapi, come ServireStack, o qualsiasi altra cosa è fresco.
Soluzione
/// <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
};
}
.
È costruttore di cordoncontent.Sembra che sia necessario specificare la codifica appropriata e MediaType
Altri suggerimenti
Non è possibile impostare direttamente un'istanza di httpContent, perché è una classe astratta.È necessario utilizzare una delle sotto-classi, a seconda della necessità.Molto probabile StringContent, che consente di impostare il valore stringa della risposta, la codifica e il tipo di supporto nel costruttore: http://msdn.microsoft.com/en-us/library/system.net.http.stringcontent.aspx
Risposta da Come posso impostare httpContent per il mio parametro HttpClient PostAsync secondo?