C# HttpClient PostAsync 将 204 变成 404

Posted

技术标签:

【中文标题】C# HttpClient PostAsync 将 204 变成 404【英文标题】:C# HttpClient PostAsync turns 204 into 404 【发布时间】:2014-01-17 10:55:24 【问题描述】:

鉴于此 WebApi 服务:

[ActionName("KillPerson")]
[HttpPost]
public void KillPerson([FromBody] long id)

    // Kill

还有这个 HttpClient PostAsync 调用:

var httpClient = new HttpClient  BaseAddress = new Uri(ClientConfiguration.ApiUrl) ;
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var serializerSettings = new JsonSerializerSettings

    PreserveReferencesHandling = PreserveReferencesHandling.Objects,
    Formatting = Formatting.Indented,
    ReferenceLoopHandling = ReferenceLoopHandling.Serialize
;
var serializedParameter = JsonConvert.SerializeObject(parameter, serializerSettings);
var httpContent = new StringContent(serializedParameter, Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync(serviceUrl, httpContent).ConfigureAwait(false);
response.EnsureSuccessStatusCode();

我希望 response.EnsureSuccessStatusCode();成功,但它会抛出 404。 有趣的是,fiddler 告诉我 webapi 服务按预期返回 204,当我调试它时,KillPerson 运行没有问题。

更新: 我已经确定只有当客户端代码位于 PCL 或 Silverlight 5 项目中时才会发生这种情况。如果我在 Windows 窗体应用程序中复制它,完全相同的代码将给出预期的 204。如果我将 Windows 窗体应用程序指向 PCL 中包含的客户端代码,它会再次给我 404。

更新2: 这解决了这个问题(尽管它让我无休止地需要这样做):

[ActionName("KillPerson")]
[HttpPost]
public HttpResponseMessage KillPerson([FromBody] long id)

    return this.Request.CreateResponse(HttpStatusCode.OK);

这重新引入了 404(提琴手仍然说 204 并且非 Silverlight 客户端运行良好)

[ActionName("KillPerson")]
[HttpPost]
public HttpResponseMessage KillPerson([FromBody] long id)

    return this.Request.CreateResponse(HttpStatusCode.NoContent);

更新 3(已解决): 终于想通了。似乎您可以选择在 Silverlight 中使用浏览器或客户端 HTTP 处理。当使用浏览器 HTTP 处理很多东西是不受支持的 - 包括各种响应代码和标头。 在调用 HttpClient 之前添加这些行修复它:

WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);

【问题讨论】:

服务上的编码是否与客户端匹配?客户端上的 404 向我建议,当它夸大响应时,它与预期不符。 是的 - 这只发生在 void (204) 方法中 - 如果我将 KillPerson 服务更改为返回一个字符串,它运行良好。 鉴于您的更新,这并不是特别有用,但我在控制台应用程序上获得了正确的功能:(返回 204)gist.github.com/brainwipe/8472430 让我认为可能设置了 AppDomain 设置或编码全球某地。 POST 请求不是给你一个 201(已创建)吗? 不幸的是,这不是我们唯一一次在我们的商店中看到 Silverligt 中 HttpClient 的奇怪行为。 WS-Trust 事务也存在类似的问题(控制台或 WinForms 应用程序的行为不一致)。非常奇怪和模糊,因为 MSFT 没有花任何时间修复 SL5。 【参考方案1】:

终于想通了。似乎您可以选择在 Silverlight 中使用浏览器或客户端 HTTP 处理。当使用浏览器 HTTP 处理很多东西是不受支持的 - 包括各种响应代码和标头。在调用 HttpClient 之前添加这些行修复它:

WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);

【讨论】:

【参考方案2】:

在方法中添加 HttpResponseMessage 返回类型是记录在案的方法,因此您找到的解决方案确实是最好的。

但是,如果您不想以这种方式更改所有 void 方法,另一种方法是添加一个委托处理程序来动态更改响应代码 - 如下所示:

public class ResponseHandler : DelegatingHandler

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    
        var response = base.SendAsync(request, cancellationToken);

        if (request.Method == HttpMethod.Post)
        
            response.Result.StatusCode = response.Result.IsSuccessStatusCode ? System.Net.HttpStatusCode.OK : response.Result.StatusCode;
        
        return response;
   

注意:这将更改所有您的发布方法的状态码(成功时)。如果您只想为特定的路线/方法完成它,则必须添加一些代码(如果您需要以不同的方式对待不同的发布方法)。

【讨论】:

以上是关于C# HttpClient PostAsync 将 204 变成 404的主要内容,如果未能解决你的问题,请参考以下文章

C# Metro HttpClient 未在 PostAsync 上接收 cookie

使用 HttpClient PostAsync 发送 C# NameValueCollection 问题

带有标题和内容c#的HttpClient PostAsync [重复]

C# HttpClient PostAsync 不适用于 django rest 框架

如何使用 C# HttpClient PostAsync 显示上传进度

HttpClient postasync,带有自定义标头和应用程序/json,用于正文 C#