PostAsJsonAsync C# - 如何为 POST 请求正确设置标头 - BAD REQUEST 400

Posted

技术标签:

【中文标题】PostAsJsonAsync C# - 如何为 POST 请求正确设置标头 - BAD REQUEST 400【英文标题】:PostAsJsonAsync C# - How to set headers correctly for POST request - BAD REQUEST 400 【发布时间】:2020-12-22 13:34:42 【问题描述】:

大家好。

我遇到了下一个问题。 我正在尝试执行 POST 请求,但是当我使用 Visual Studio Code 的调试器编译和执行它时,我收到 400 Bad Request 的错误。 无论如何,当我在 Postman 中执行相同的 POST 请求时,我会收到一个 200 OK 状态请求,其中包含继续进行下一部分工作所需的所有值。

此外,请求中有一个基本身份验证,在这种情况下,我将它包含在 Postman 中并且它工作正常。另一方面,在我的 C# 脚本中,我是这样执行的:

*这是我的模型,其中包含了我的所有数据,用于将对象序列化为 JSON。

 public class patientMediktor
    public string deviceId  get; set;         
    public string deviceType  get; set; 
    public string apiVersion  get; set; 
    public string language  get; set; 
    public externUserClass externUser get;set; 

    public class externUserClass
        public externUserClass(string partnerExternalId, string username, string newPassword, string gender)
            this.partnerExternalId = partnerExternalId;
            this.username = username;
            this.newPassword = newPassword;
            this.gender = gender;
        
        public string partnerExternalId  get; set; 
        public string username  get; set; 
        public string newPassword  get; set; 
        public string gender  get; set; 
    
    public string includeAuthToken get; set; 

*这是我创建 POST 请求的 Helper 类。我插入了我需要的所有数据,然后我将对象序列化为 JSON,因为你们中的一些人建议我这样做。比较干净。

 public async Task<string> MediktorHubCrearUsuario(string conf, string userId, string sexo, string deviceId)
    
        var sexoStr = "";  
        if(sexo == "MALE") 
            sexoStr = "MALE";
         else if(sexo == "FEMALE") 
            sexoStr = "FEMALE";
        

        var guid = Guid.NewGuid().ToString(); // guid para el username y el password
        var data = new patientMediktor();
        data.deviceId = userId;
        data.deviceType = "WEB";
        data.apiVersion = "4.0.3";
        data.language = "es_ES";
        data.externUser = new patientMediktor.externUserClass(userId, guid, guid, sexoStr); // extern user
        data.includeAuthToken = "true";

        string output = JsonConvert.SerializeObject(data);

        var ServerMedictor = conf;
        var client =  new HttpClientBaseAddress = new Uri(ServerMedictor);
        MediaType = "application/json";
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaType)); //ACCEPT header
        client.DefaultRequestHeaders.Authorization =  new AuthenticationHeaderValue("xxxxxx", "xxxxxxxxxxxx");
        var Client = client;
        var request = await Client.PostAsJsonAsync("externUser", output);

        request.EnsureSuccessStatusCode();
        var status = await request.Content.ReadAsStringAsync();
        return status;
    

如果有人对如何处理这个问题有任何线索,那将非常感激。 我将继续尝试组合如何解决这个问题的替代方案。 *尽管进行了修改,但我仍然遇到同样的问题。我确实序列化了该对象,并且以我需要的方式得到它。但是,每当涉及到请求时,它都会给我一个 400 Bad Request。

诚挚的问候和感谢

【问题讨论】:

我会忽略您在 VS 中遇到的任何错误,直到您修复 400 的响应状态并获得 200 OK。该错误是由于服务器不喜欢该请求,因此对响应的任何处理都是没有意义的。 c# 中的默认标头与 Postman 不同。最好的调试方法是使用像 wireshark 或 fiddler 这样的嗅探器,并将 Postman 头文件与 c# 头文件进行比较。然后让 c# 看起来像 Postman。 400 错误的原因有很多。通常它只是添加用户代理标头,它指定您的代码正在模拟的浏览器类型。 【参考方案1】:

尝试使用 PostAsync 而不是 'PostAsJsonAsync'

var content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");

var request = await httpClient.PostAsync(requestUrl, content);

请在HttpClient not supporting PostAsJsonAsync method C#找到有关“PostAsJsonAsync”的更多详细信息

【讨论】:

【参考方案2】:

看来您应该删除以下行末尾的逗号:

sexoStr = "\"gender\": \"MALE\",";
...
sexoStr = "\"gender\": \"FEMALE\",";

一般来说,更喜欢使用模型类并将它们序列化(使用Newtonsoft.Json (example) 或System.Text.Json),而不是硬编码字符串。

【讨论】:

这是一回事,我已经做到了。由于某种原因,我的机器仍在缓存之前的请求(包括逗号)。我清除了缓存和 cookie,但仍有一些奇怪的东西仍然存在。我也会尝试序列化我的 JSON。会让你知道它是否有效。谢谢 很难相信 POST 请求被缓存了 (see this)。您是否有权访问服务器端以便可以看到传入的请求?如果没有,您可能应该使用fiddler 或wireshark 来查看它。【参考方案3】:

答案就在这里。 Basic Auth 标头的构造从一开始就是错误的。为了对其进行编码,我必须像 new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray)); 这样将其传递给请求。 我还用 PostAsync 替换了 PostAsJsonAsync。它就像一个魅力! 最后,我得到了一个状态码 200 OK,其中包含我需要传递给我的视图的数据。

public async Task<string> CreateUser(string conf, string userId, string sexo, string deviceId)
        
            var sexoStr = "";  
            if(sexo == "MALE") 
                sexoStr = "MALE";
             else if(sexo == "FEMALE") 
                sexoStr = "FEMALE";
            

            var guid = Guid.NewGuid().ToString(); // guid para el username y el password
            var data = new patientMediktor();
            data.deviceId = userId;
            data.deviceType = "WEB";
            data.apiVersion = "4.0.3";
            data.language = "es_ES";
            data.externUser = new patientMediktor.externUserClass(userId, guid, guid, sexoStr); // extern user
            data.includeAuthToken = true;

            string json = JsonConvert.SerializeObject(data);
            var Client =  new HttpClient();
            var prueba = "https://xxxxxx.com:443/";
            Client.BaseAddress = new Uri(prueba);

            var byteArray = Encoding.ASCII.GetBytes("xxxxxxxx:xxxxxxxxx");
            Client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
            var response = Client.PostAsync("backoffice/services/externUser", new StringContent(json, Encoding.UTF8, "application/json")).Result;

            response.EnsureSuccessStatusCode();
            var respuesta = await response.Content.ReadAsStringAsync();
            return respuesta;
   

【讨论】:

以上是关于PostAsJsonAsync C# - 如何为 POST 请求正确设置标头 - BAD REQUEST 400的主要内容,如果未能解决你的问题,请参考以下文章

如何为 C# 项目生成 .tlh 文件

C#:如何为部分类中的属性设置默认值?

c# 如何为聚合对象的变量创建属性?

如何为我的 C# 应用程序创建产品密钥?

如何为泛型类编写 C# 扩展方法

如何为 C# 中的枚举类型应用 InterLocked.Exchange?