Home > Back-end >  Rewriting a Java HttpURLConnection method using C# HttpClient
Rewriting a Java HttpURLConnection method using C# HttpClient

Time:09-27

I've got a working Java method that uses java.net.HttpURLConnection that I should re-implement in C# using the .NET HttpClient.

Java method:

public static String getMyThingAPIToken() throws IOException{
    URL apiURL = new URL("https://myThingAPI/token");
    HttpURLConnection apiConnection = (HttpURLConnection) apiURL.openConnection();
    apiConnection.setRequestMethod("POST");
    apiConnection.setDoOutput(true);
    String apiBodyString = "myThingAPI login id and secret key";
    byte[] apiBody = apiBodyString.getBytes(StandardCharsets.UTF_8);

    OutputStream apiBodyStream = apiConnection.getOutputStream();
    apiBodyStream.write(apiBody);
    
    StringBuffer apiResponseBuffer;
    try (BufferedReader in = new BufferedReader(new InputStreamReader(apiConnection.getInputStream()))){
        String inputline;
        apiResponseBuffer = new StringBuffer();
        while((inputline = in.readLine()) != null) {
            apiResponseBuffer.append(inputline);
        }
    }
}

So far, my C# looks like below, and you'll notice that this early form of my implementation does not interpret the response. Nor does it have a string return type required for the token string.

This is because when I test it, the response has: StatusCode: 400 ReasonPhrase: 'Bad Request'

So something in my apiBody byte array or use of PostAsync must be different to what the Java method does, but I cannot work out what it could be.

public async static Task<HttpResponseMessage> getMyThingAPIToken(HttpClient client)
{
    var apiURI = new Uri("https://myThingAPI/token");
    string apiBodystring = "myThingAPI login id and secret key";
    byte[] apiBody = System.Text.Encoding.UTF8.GetBytes(apiBodystring);
    var response = await client.PostAsync(apiURI, new ByteArrayContent(apiBody));
    return response;
}

CodePudding user response:

The Java code doesn't specify a type which means that by default the request uses application/x-www-form-urlencoded. This is used for FORM POST requests.

The default content type for ByteArrayContent on the other hand is application/octet-stream while for StringContent it's text/plain. FORM content is used through the FormUrlEncoodedContent class which can accept any Dictionary<string,string> as payload.

The input in the question is not in a x-www-form-urlencoded form so either it's not the real content or the API is misusing content types.

Assuming the API accepts proper x-www-form-urlencoded content, the following should work:

var data=new Dictionary<string,string>{
    ["login"]=....,
    ["secret"]=.....,
    ["someOtherField"]=....
};
var content= new FormUrlEncodedContent(data);
var response=await client.PostAsync(apiURI,content);

To send any text using application/x-www-form-urlencoded, we need to specify the content type in StringContent's constructor:

var contentType="application/x-www-form-urlencoded";
var content= new StringContent(apiBodyString, Encoding.UTF8,contentType);
var response=await client.PostAsync(apiURI,content);

CodePudding user response:

Can you try using following code:

                    client.BaseAddress = new Uri("https://myThingAPI/");
                    var message = new HttpRequestMessage(HttpMethod.Post, "/token");

                    // Add your login id and secret key here with the format you want to send
                    message.Content = new StringContent(string.Format("userName={0}&password={1}", UserName, Password));
                    var result = await client.SendAsync(message);
                    return result;
                
  • Related