简体   繁体   English

C#HttpClient PostAsync将204变为404

[英]C# HttpClient PostAsync turns 204 into 404

Given this WebApi service: 鉴于此WebApi服务:

[ActionName("KillPerson")]
[HttpPost]
public void KillPerson([FromBody] long id)
{
    // Kill
}

And this HttpClient PostAsync call: 而这个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();

I would expect response.EnsureSuccessStatusCode(); 我希望response.EnsureSuccessStatusCode(); to succede but it throws a 404 instead. 成功,但它会抛出404。 The funny thing is that fiddler tells med that the webapi service is returning 204 as expected and when I debug it the KillPerson runs without issue. 有趣的是,fiddler告诉med,webapi服务按预期返回204,当我调试它时,KillPerson运行没有问题。

Update: I Have determined that this only happens when the client code is within a PCL or Silverlight 5 project. 更新:我已确定只有在客户端代码位于PCL或Silverlight 5项目中时才会发生这种情况。 The exact same code will give the expected 204 if I duplicate it in a Windows forms application. 如果我在Windows窗体应用程序中复制它,完全相同的代码将给出预期的204。 If i point the Windows Forms app to client code contained in a PCL it gives me the 404 Again. 如果我将Windows窗体应用程序指向PCL中包含的客户端代码,它会给我404 Again。

Update2: This resolves the issue (though it bothers me no end that I should need to do it): Update2:这解决了这个问题(尽管让我感到困扰,我不应该这样做):

[ActionName("KillPerson")]
[HttpPost]
public HttpResponseMessage KillPerson([FromBody] long id)
{
    return this.Request.CreateResponse(HttpStatusCode.OK);
}

This reintroduces the 404 (fiddler still says 204 and non-silverlight client runs fine) 这重新引入了404(小提琴手仍称204和非银光客户端运行正常)

[ActionName("KillPerson")]
[HttpPost]
public HttpResponseMessage KillPerson([FromBody] long id)
{
    return this.Request.CreateResponse(HttpStatusCode.NoContent);
}

Update 3 (resolved): Finally figured this out. 更新3(已解决):最后想出来了。 Seems you get a choice of using either browser or client HTTP handling in Silverlight. 似乎您可以选择在Silverlight中使用浏览器或客户端HTTP处理。 When using browser HTTP handling a lot of stuff is unsupported - including various response codes and headers. 使用浏览器HTTP处理时,许多内容都不受支持 - 包括各种响应代码和标头。 Adding these lines before calling HttpClient fixed it: 在调用HttpClient之前添加这些行修复它:

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

Finally figured this out. 终于搞清楚了。 Seems you get a choice of using either browser or client HTTP handling in Silverlight. 似乎您可以选择在Silverlight中使用浏览器或客户端HTTP处理。 When using browser HTTP handling a lot of stuff is unsupported - including various response codes and headers. 使用浏览器HTTP处理时,许多内容都不受支持 - 包括各种响应代码和标头。 Adding these lines before calling HttpClient fixed it: 在调用HttpClient之前添加这些行修复它:

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

Adding the HttpResponseMessage returntype to the method is the documented way of doing this, so the solution you have found is the best really. 将HttpResponseMessage返回类型添加到方法中是记录的方法,因此您找到的解决方案确实是最好的。

But if you don't want to change all your void methods that way, an alternative could be to add a delegating handler to change the response code on the fly - something like this: 但是,如果您不想以这种方式更改所有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;
   }
}

Note: This will change the statuscode for all your post methods (when successful). 注意:这将更改所有发布方法的状态代码(成功时)。 You would have to add some code if you only want it done for specific routes/methods (if you need different post methods to be treated differently). 如果您只想为特定的路径/方法完成某些代码,则必须添加一些代码(如果您需要不同的后处理方法,则需要区别对待)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM