使用 C# HttpClient 重写 Java HttpURLConnection 方法

Rewriting a Java HttpURLConnection method using C# HttpClient

我有一个使用 java.net.HttpURLConnection 的有效 Java 方法,我应该使用 .NET HttpClient 在 C# 中重新实现它。

Java方法:

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);
        }
    }
}

到目前为止,我的 C# 如下所示,您会注意到我的这种早期实现形式不会解释响应。它也没有令牌字符串所需的字符串 return 类型。

这是因为我测试的时候,响应有: 状态码:400 ReasonPhrase: 'Bad Request'

所以我的 apiBody 字节数组中的某些内容或 PostAsync 的使用必须与 Java 方法所做的不同,但我无法弄清楚它可能是什么。

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;
}

您可以尝试使用以下代码吗:

                    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;
                

Java 代码未指定类型,这意味着 by default 请求使用 application/x-www-form-urlencoded。这用于 FORM POST 请求。

另一方面,ByteArrayContent 的默认内容类型是 application/octet-stream,而 StringContent 的默认内容类型是 text/plain。 FORM 内容通过 FormUrlEncoodedContent class 使用,它可以接受任何 Dictionary<string,string> 作为有效负载。

问题中的输入 不是 x-www-form-urlencoded 形式,所以它不是真正的内容,或者 API 滥用了内容类型。

假设 API 接受适当的 x-www-form-urlencoded 内容,以下应该有效:

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

要使用 application/x-www-form-urlencoded 发送任何文本,我们需要在 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);