0

I am required to connect to a HTTPS server and post data in the form of a Dictionary to it. The server API is created by my teacher and he has provided Python code on how to post to the server, using the Python library Reguests (see docs).

The Python template using Requests

def call_server(move): //Move is an integer value
   res = requests.post(SERVER_ADRESS,
                       data={
                           "id": ID, 
                           "move": move, 
                           "api_key": API_KEY,
                       })

where of course SERVER_ADRESS, ID, move and API_KEY all are provided.

I am trying to rewrite this functionality in C# using the HttpClient class. I have tried using the method PostAsync in HttpClient (see docs) by using both a StringConent and a FormUrlEncodedContent object as the HttpContent (can be seen below). However both methods results in the server responding with the error code 422 - Unprocessable Entity. Which apperently means

The server understands the content type and syntax of the request entity, but still server is unable to process the request for some reason.

My template using HttpClient

class HttpHandler
{
   static readonly HttpClient client = new HttpClient();
   static readonly string SERVER_ADRESS = ...
   static readonly string ID = ...
   static readonly string APIKey = ...
   Dictionary<string, string> data;
   
   public void callServer(int move)
   {
      data = new Dictionary<string, string>();
      data.Add("id", ID);
      data.Add("move", move.ToString());
      data.Add("api_key", APIKey);
      string serialized = JsonConvert.SerializeObject(data); //From Newtonsoft.Json
      HttpContent stringCont = new StringContent(serialized,Encoding.UTF8,"application/json");    
      HttpContent byteCont = new FormUrlEncodedContent(data);
            
      var resStringCont = client.PostAsync(SERVER_ADDRESS, stringCont);
      //var resByteCont = client.PostAsync(SERVER_ADDRESS, byteCont);
   } 
}

Anyone more experienced with Https that can figure out why I can't successfully post to the server?

MarkusAnd
  • 750
  • 7
  • 21
  • Does this answer it? https://stackoverflow.com/questions/28468484/how-to-post-json-with-httpclient-using-c – Jim W Feb 02 '22 at 18:58
  • FWIW unless there is a certificate problem, which it doesn't seem to be, I doubt the issue is related to HTTPS – Jim W Feb 02 '22 at 19:02
  • Have you checked the json? Does it look ok? – Poul Bak Feb 02 '22 at 19:06
  • @PoulBak The Json looks fine! – MarkusAnd Feb 02 '22 at 20:26
  • Trying to find some documentation on python-requests .post method.... I can only guess that using `data=` will send a "application/x-www-form-urlencoded" content type. – Jeremy Lakeman Feb 04 '22 at 01:07
  • Even searching the source code doesn't make that obvious (https://github.com/psf/requests/search?q=application%2Fx-www-form-urlencoded) – Jeremy Lakeman Feb 04 '22 at 01:13
  • In the StringContent case you're JSON-serializing that move property as a string (e.g. `"move": "5"`) rather than a number (e.g. `"move": 5`). It might be worth a try to use a `Dictionary` in that case and don't `ToString()` the move. – Todd Menier Feb 06 '22 at 15:15

1 Answers1

1

Try using this approach, it works with the server I am sending data to.

var content = new StringContent("{some:json}");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                
client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json;"));
                
HttpResponseMessage response = await client.PostAsync("https://SERVER_ADRESS", content);

I suspect the request header is the reason, and send StringContent instead of FormUrlEncodedContent

Jim W
  • 4,866
  • 1
  • 27
  • 43
  • Unfortunately this didn't work, I managed to solve it by simply running a Python script containing the provided template. Thanks for your efforts though! – MarkusAnd Feb 04 '22 at 17:19