MVC C# Web App 中的 400 Bad Request 但不是 Postman
400 Bad Request in MVC C# Web App but not Postman
我已经使用了以下方法几个小时了,但无法PUT
我对外部 Ellucian Ethos API
.
的更新
public async Task<string> UpdatePersonH11()
{
var token = await GetAccessTokenAsync("TokenApi", "value");
var guid = await GetPersonGUID(token);
Uri personsURI = new Uri(string.Format("https://URLtoAPI" + guid));
H11Model h11Data = new H11Model
{
h11 = new h11
{
extendedPersonUser2 = "2021/FA",
extendedPersonUser3 = "OUT",
extendedPersonUser4 = DateTime.Now.ToShortDateString()
}
};
using (var client = new HttpClient())
{
client.BaseAddress = personsURI;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Accept", "application/vnd.hedtech.integration.v12+json");
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate, br");
client.DefaultRequestHeaders.Add("Connection", "keep-alive");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
var responseString = "";
var content = JsonSerializer.Serialize(h11Data);
**using (HttpResponseMessage response = await client.PutAsJsonAsync(personsURI, content))** Debugger stops here and gives me a 400 Bad Request
{
if (response.IsSuccessStatusCode)
{
responseString = await response.Content.ReadAsStringAsync();
}
else
{
log.Debug("Error in response." + response);
return "";
}
return responseString;
}
}
}
这是 Json 正在为变量 content
序列化以通过 PutAsJsonAsync
发送的 json
。
{
"h11":
{
"extendedPersonUser2":"2021/FA",
"extendedPersonUser3":"OUT",
"extendedPersonUser4":"8/5/2021",
}
}
H11型号
public class H11Model
{
[JsonProperty("h11")]
public h11 h11 { get; set; }
}
public class h11
{
[JsonProperty("extendedPersonUser2")]
public string extendedPersonUser2 { get; set; }
[JsonProperty("extendedPersonUser3")]
public string extendedPersonUser3 { get; set; }
[JsonProperty("extendedPersonUser4")]
public string extendedPersonUser4 { get; set; }
[JsonProperty("extendedPersonUser5")]
public string extendedPersonUser5 { get; set; }
[JsonProperty("extendedPersonUser6")]
public string extendedPersonUser6 { get; set; }
[JsonProperty("extendedPersonUser7")]
public string extendedPersonUser7 { get; set; }
[JsonProperty("extendedPersonUser8")]
public string extendedPersonUser8 { get; set; }
[JsonProperty("extendedPersonUser9")]
public string extendedPersonUser9 { get; set; }
[JsonProperty("extendedPersonUser10")]
public string extendedPersonUser10 { get; set; }
}
我读到 PutAsJsonAsync
不需要先序列化内容,但是当我注释掉 var content = JsonSerializer.Serialize(h11Data);
时,我得到一个 406 Not Acceptable
错误,这让我相信我确实需要先序列化内容。
这是我从调试器返回的请求消息:
{
Method: PUT,
RequestUri: 'API URI',
Version: 1.1,
Content: System.Net.Http.ObjectContent`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=token]],
Headers:
{
Authorization: Bearer 'token is here'
Accept: application/vnd.hedtech.integration.v12+json
Content-Type: application/json; charset=utf-8
Content-Length: 293
}
}
这是回复信息:
{
StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Connection: keep-alive
pragma: no-cache
hedtech-ethos-integration-application-id: GUID
hedtech-ethos-integration-application-name: Colleague
vary: origin
access-control-expose-headers: x-max-page-size,x-media-type,x-total-count,x-content-restricted,hedtech-ethos-integration-application-id,hedtech-ethos-integration-application-name,hedtech-ethos-integration-proxy-generated
Cache-Control: no-cache
Date: Fri, 06 Aug 2021 13:41:56 GMT
Server: Microsoft-IIS/10.0
Content-Length: 447
Content-Type: text/plain; charset=utf-8
Expires: -1
}
}
如果有人能帮我指出正确的方向,我将不胜感激。我以前没有以这种方式使用过 API,所以这对我来说是一个新领域,我对此感到困惑。
编辑:有效的最终代码(片段):
H11Model h11Data = new H11Model
{
h11 = new h11
{
extendedPersonUser5 = "OUT", // fall term
extendedPersonUser6 = DateTime.Now.ToShortDateString()
}
};
using (var client = new HttpClient())
{
client.BaseAddress = personsURI;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Accept", "application/vnd.hedtech.integration.v12+json");
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate, br");
client.DefaultRequestHeaders.Add("Connection", "keep-alive");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
var responseString = "";
//var content = JsonSerializer.Serialize(h11Data);
using (HttpResponseMessage response = await client.PutAsJsonAsync(personsURI, h11Data))
{
if (response.IsSuccessStatusCode)
{
try
{
responseString = await response.Content.ReadAsStringAsync();
}
catch (NotSupportedException ex) // When content type is not valid
{
log.Debug("The content type is not supported.", ex);
}
catch (JsonException ex) // Invalid JSON
{
log.Debug("Invalid JSON.", ex);
}
}
else
{
log.Debug("Error in response." + response);
return "";
}
return responseString;
}
}
如果服务没有覆盖 HTTP 代码的含义并按照 RFC 中的描述使用它们,那么
The 406 (Not Acceptable) status code indicates that the target resource does not have a current representation that would be acceptable to the user agent, according to the proactive negotiation header fields received in the request (Section 5.3), and the server is unwilling to supply a default representation.
简而言之,Accept
、Accept-Encoding
、Accept-Charset
或 Accept-Language
HTTP header 的值无效或未按服务预期定义。
在所描述的情况下,至少有两个这样的 header 通过 HttpClient.DefaultRequestHeaders
collection 设置。它们的值需要与服务文档进行比较。并且需要注意的是,在一般情况下 Accept-Encoding
header 应该设置为 HttpClientHandler.AutomaticDecompression
属性 而不是 DefaultRequestHeaders
collection,否则它将被忽略。
The 400 (Bad Request) status code indicates that the server cannot or
will not process the request due to something that is perceived to be
a client error (e.g., malformed request syntax, invalid request
message framing, or deceptive request routing).
例如,服务期望{ "h11": { "extendedPersonUser2": ...
JSONobject;但取而代之的是,服务接收 "{ \"h11\": { \"extendedPersonUser2\": ...
并且无法反序列化它。
正如评论中已经提到的,PutAsJsonAsync
extension method and HttpClient.PutAsync
method with StringContent
之间存在差异。第一个向指定的 Uri 发送 PUT 请求,其中包含在请求 body 中序列化为 JSON 的值。 PutAsync
方法发送内容参数定义的原始内容。
因此,示例中的代码
string content = JsonSerializer.Serialize(h11Data);
... = await client.PutAsJsonAsync(personsURI, content);
使用 PutAsJsonAsync
并发送另外序列化为 JSON 的 JSON 字符串。结果服务收到以下内容 "{ \"h11\": { \"extendedPersonUser2\": ...
.
通常,当使用PutAsJsonAsync
扩展方法时,不需要额外的JSON序列化。内容 object 可以直接传递给 PutAsJsonAsync
扩展方法。
... = await client.PutAsJsonAsync(personsURI, h11Data);
在这种情况下,请求将作为 { "h11": { "extendedPersonUser2": ...
.
发送
有多个 PutAsJsonAsync
扩展方法重载也接受 JsonSerializerOptions
自定义 JSON 序列化。重要的是要注意 PutAsJsonAsync
在内部使用 HttpClient.PutAsync
方法和 StringContent
来发送请求。
我已经使用了以下方法几个小时了,但无法PUT
我对外部 Ellucian Ethos API
.
public async Task<string> UpdatePersonH11()
{
var token = await GetAccessTokenAsync("TokenApi", "value");
var guid = await GetPersonGUID(token);
Uri personsURI = new Uri(string.Format("https://URLtoAPI" + guid));
H11Model h11Data = new H11Model
{
h11 = new h11
{
extendedPersonUser2 = "2021/FA",
extendedPersonUser3 = "OUT",
extendedPersonUser4 = DateTime.Now.ToShortDateString()
}
};
using (var client = new HttpClient())
{
client.BaseAddress = personsURI;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Accept", "application/vnd.hedtech.integration.v12+json");
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate, br");
client.DefaultRequestHeaders.Add("Connection", "keep-alive");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
var responseString = "";
var content = JsonSerializer.Serialize(h11Data);
**using (HttpResponseMessage response = await client.PutAsJsonAsync(personsURI, content))** Debugger stops here and gives me a 400 Bad Request
{
if (response.IsSuccessStatusCode)
{
responseString = await response.Content.ReadAsStringAsync();
}
else
{
log.Debug("Error in response." + response);
return "";
}
return responseString;
}
}
}
这是 Json 正在为变量 content
序列化以通过 PutAsJsonAsync
发送的 json
。
{
"h11":
{
"extendedPersonUser2":"2021/FA",
"extendedPersonUser3":"OUT",
"extendedPersonUser4":"8/5/2021",
}
}
H11型号
public class H11Model
{
[JsonProperty("h11")]
public h11 h11 { get; set; }
}
public class h11
{
[JsonProperty("extendedPersonUser2")]
public string extendedPersonUser2 { get; set; }
[JsonProperty("extendedPersonUser3")]
public string extendedPersonUser3 { get; set; }
[JsonProperty("extendedPersonUser4")]
public string extendedPersonUser4 { get; set; }
[JsonProperty("extendedPersonUser5")]
public string extendedPersonUser5 { get; set; }
[JsonProperty("extendedPersonUser6")]
public string extendedPersonUser6 { get; set; }
[JsonProperty("extendedPersonUser7")]
public string extendedPersonUser7 { get; set; }
[JsonProperty("extendedPersonUser8")]
public string extendedPersonUser8 { get; set; }
[JsonProperty("extendedPersonUser9")]
public string extendedPersonUser9 { get; set; }
[JsonProperty("extendedPersonUser10")]
public string extendedPersonUser10 { get; set; }
}
我读到 PutAsJsonAsync
不需要先序列化内容,但是当我注释掉 var content = JsonSerializer.Serialize(h11Data);
时,我得到一个 406 Not Acceptable
错误,这让我相信我确实需要先序列化内容。
这是我从调试器返回的请求消息:
{
Method: PUT,
RequestUri: 'API URI',
Version: 1.1,
Content: System.Net.Http.ObjectContent`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=token]],
Headers:
{
Authorization: Bearer 'token is here'
Accept: application/vnd.hedtech.integration.v12+json
Content-Type: application/json; charset=utf-8
Content-Length: 293
}
}
这是回复信息:
{
StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Connection: keep-alive
pragma: no-cache
hedtech-ethos-integration-application-id: GUID
hedtech-ethos-integration-application-name: Colleague
vary: origin
access-control-expose-headers: x-max-page-size,x-media-type,x-total-count,x-content-restricted,hedtech-ethos-integration-application-id,hedtech-ethos-integration-application-name,hedtech-ethos-integration-proxy-generated
Cache-Control: no-cache
Date: Fri, 06 Aug 2021 13:41:56 GMT
Server: Microsoft-IIS/10.0
Content-Length: 447
Content-Type: text/plain; charset=utf-8
Expires: -1
}
}
如果有人能帮我指出正确的方向,我将不胜感激。我以前没有以这种方式使用过 API,所以这对我来说是一个新领域,我对此感到困惑。
编辑:有效的最终代码(片段):
H11Model h11Data = new H11Model
{
h11 = new h11
{
extendedPersonUser5 = "OUT", // fall term
extendedPersonUser6 = DateTime.Now.ToShortDateString()
}
};
using (var client = new HttpClient())
{
client.BaseAddress = personsURI;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Accept", "application/vnd.hedtech.integration.v12+json");
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate, br");
client.DefaultRequestHeaders.Add("Connection", "keep-alive");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
var responseString = "";
//var content = JsonSerializer.Serialize(h11Data);
using (HttpResponseMessage response = await client.PutAsJsonAsync(personsURI, h11Data))
{
if (response.IsSuccessStatusCode)
{
try
{
responseString = await response.Content.ReadAsStringAsync();
}
catch (NotSupportedException ex) // When content type is not valid
{
log.Debug("The content type is not supported.", ex);
}
catch (JsonException ex) // Invalid JSON
{
log.Debug("Invalid JSON.", ex);
}
}
else
{
log.Debug("Error in response." + response);
return "";
}
return responseString;
}
}
如果服务没有覆盖 HTTP 代码的含义并按照 RFC 中的描述使用它们,那么
The 406 (Not Acceptable) status code indicates that the target resource does not have a current representation that would be acceptable to the user agent, according to the proactive negotiation header fields received in the request (Section 5.3), and the server is unwilling to supply a default representation.
简而言之,Accept
、Accept-Encoding
、Accept-Charset
或 Accept-Language
HTTP header 的值无效或未按服务预期定义。
在所描述的情况下,至少有两个这样的 header 通过 HttpClient.DefaultRequestHeaders
collection 设置。它们的值需要与服务文档进行比较。并且需要注意的是,在一般情况下 Accept-Encoding
header 应该设置为 HttpClientHandler.AutomaticDecompression
属性 而不是 DefaultRequestHeaders
collection,否则它将被忽略。
The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
例如,服务期望{ "h11": { "extendedPersonUser2": ...
JSONobject;但取而代之的是,服务接收 "{ \"h11\": { \"extendedPersonUser2\": ...
并且无法反序列化它。
正如评论中已经提到的,PutAsJsonAsync
extension method and HttpClient.PutAsync
method with StringContent
之间存在差异。第一个向指定的 Uri 发送 PUT 请求,其中包含在请求 body 中序列化为 JSON 的值。 PutAsync
方法发送内容参数定义的原始内容。
因此,示例中的代码
string content = JsonSerializer.Serialize(h11Data);
... = await client.PutAsJsonAsync(personsURI, content);
使用 PutAsJsonAsync
并发送另外序列化为 JSON 的 JSON 字符串。结果服务收到以下内容 "{ \"h11\": { \"extendedPersonUser2\": ...
.
通常,当使用PutAsJsonAsync
扩展方法时,不需要额外的JSON序列化。内容 object 可以直接传递给 PutAsJsonAsync
扩展方法。
... = await client.PutAsJsonAsync(personsURI, h11Data);
在这种情况下,请求将作为 { "h11": { "extendedPersonUser2": ...
.
有多个 PutAsJsonAsync
扩展方法重载也接受 JsonSerializerOptions
自定义 JSON 序列化。重要的是要注意 PutAsJsonAsync
在内部使用 HttpClient.PutAsync
方法和 StringContent
来发送请求。