等待actionContext.Request.Content.ReadAsStringAsync()返回一个空字符串

时间:2019-04-24 16:25:42

标签: c# asp.net-web-api asp.net-web-api2

首先

var myString = await actionContext.Request.Content.ReadAsStringAsync();

应该一直有效。但事实并非如此。我们开始:

AirplaneController.cs

[ValidateAirplane]
[HydrateAirplane]
public class AirplaneController : ApiController

ValidateAirplane.cs(请参见神奇的魔术句)

public class ValidateAirplaneAttribute : FilterAttribute, IAuthorizationFilterpublic class ValidateAirplaneAttribute : FilterAttribute, IAuthorizationFilter
...
public async Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
    var json = await actionContext.Request.Content.ReadAsStringAsync(); // <-- amazing magic line
    return await continuation();
}

HydrateAirplane.cs

public class HydrateAirplaneAttribute : FilterAttribute, IActionFilter
...
public async Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
    var json = await actionContext.Request.Content.ReadAsStringAsync();
    return await continuation();
}

如果我注释掉amazing magic line,则json中的ExecuteAuthorizationFilterAsync作为空字符串返回。但是,如果我不注释掉amazing magic line,我会得到json(来自客户端的飞机JSON)。

起初,我认为这可能是时间问题,因此在尝试读取json之前,我尝试在await Task.Delay(5000)中进行HydrateAirplane.cs,但是它没有任何作用。

有什么问题吗?

1 个答案:

答案 0 :(得分:0)

这不是解决方法,而是答案。如果您有更好的答案,请分享。我注意到那里有一个ReadAsStreamAsync,我能够使它正常工作。也许这是WebAPI中的错误?我在github上找不到代码,所以我不确定。我的解决方法是使用此扩展方法代替ReadAsStringAsync

public async static Task<string> GetRequestBody(this HttpActionContext actionContext)
{
    var bodyStream = await actionContext.Request.Content.ReadAsStreamAsync();
    bodyStream.Position = 0;

    var bytes = new byte[bodyStream.Length];
    await bodyStream.ReadAsync(bytes, 0, bytes.Length);

    bodyStream.Position = 0; // <-- i don't know why but this line is important. it doesn't work on subsequent calls without this. ...to be clear, it absolutely should work. i consider this to be a WebAPI work around. that is, i should not have to ever even think about this.

    return Encoding.ASCII.GetString(bytes);
}

未包装在using中的原因是包装在using中,但随后WebAPI开始抛出流是不可读的错误,我想这意味着它们使用与内部返回给您的流完全相同的流。