title: How do I send arbitrary JSON data, with a custom header, to a REST server?
body: <p>TL;DR -- How do I send a JSON string to a REST host with an auth header?  I've tried 3 different approaches found one that works with anonymous types.  Why can't I use anonymous types?  I need to set a variable called "Group-Name", and a hyphen isn't a valid C# identifier.</p>
  
  <p><strong>Background</strong></p>
  
  <p>I need to POST JSON but am unable to get the body and the content type correct</p>
  
  <p><strong>Function #1 - Works with anonymous types</strong></p>
  
  <p>The content type and data is correct,  but I don't want to use anonymous types.  I want to use a string</p>
  
  <pre><code>  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;
          } 
      }
  </code></pre>
  
  <p><strong>Output #1</strong></p>
  
  <p>Content type and data is correct when using AnonymousTypes + PostAsJsonAsync, but I don't want to use anonymous types.</p>
  
  <pre><code>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"}
  </code></pre>
  
  <p><strong>Function #2 - Doesn't work as expected</strong></p>
  
  <p>Take a string and put it into a StringContent object.  This has a side effect of changing the content type.</p>
  
  <pre><code>  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;
          } 
      }
  </code></pre>
  
  <p><strong>Output #2</strong></p>
  
  <p>Content type is wrong when using StringContent + PostAsync</p>
  
  <pre><code>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
  </code></pre>
  
  <p><strong>Function #3 - Doesn't work as expected</strong></p>
  
  <p>Since I know <code>PostAsJsonAsync</code> sets the contentType correctly, lets use that method.  (doesn't work)</p>
  
  <pre><code>    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;
          } 
      }
  </code></pre>
  
  <p><strong>Output #3</strong></p>
  
  <p>Content type is correct, POST body is wrong when using StringContent + PostAsJsonAsync</p>
  
  <pre><code>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"]}]}
  </code></pre>
  
  <p><strong>Question</strong></p>
  
  <p>All I want to do is send JSON as a string, or dynamic object defined at runtime, to a server, with HTTP content type correct, and with a special 'Auth-Token' header.</p>
  
  <p>Any example, if not using WebAPI, such as servicestack, or anything else is cool.</p>