【问题标题】:C# HttpClient PostAsync turns 204 into 404C# HttpClient PostAsync 将 204 变成 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。

标签: c# asp.net-web-api httpclient silverlight-5.0


【解决方案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;
       }
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多