响应内容长度不匹配:写入的字节太少

pwr*_*imo 5 c# asp.net-authentication kestrel-http-server asp.net-core

我的 ASP.NET Core 应用程序使用“开箱即用”的外部登录身份验证。我想要实现的 - 在 facebook 挑战中,我想包装重定向 url 并将其作为 json 返回以在 jquery 前端使用。但请求结束后,我在浏览器中看到 500 错误,在应用程序控制台中看到下一个错误:

失败:Microsoft.AspNetCore.Server.Kestrel[13] 连接 ID“0HLV651D6KVJC”,请求 ID“0HLV651D6KVJC:00000005”:应用程序抛出了一个未处理的异常。System.InvalidOperationException:响应内容长度不匹配:写入的字节太少(470 个中的 0 个)。

我的外部登录操作,没什么特别看的

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public IActionResult ExternalLogin(string provider, string returnUrl = null)
{
    // Request a redirect to the external login provider.
    var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { returnUrl });
    var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
    return Challenge(properties, provider);
}
Run Code Online (Sandbox Code Playgroud)

脸书认证配置:

services.AddAuthentication().AddFacebook(facebookOptions =>
{
    facebookOptions.AppId = Configuration["Authentication:Facebook:AppId"];
    facebookOptions.AppSecret = Configuration["Authentication:Facebook:AppSecret"];

    facebookOptions.Events.OnRedirectToAuthorizationEndpoint =
        async (x) =>
        {

            UTF8Encoding encoding = new UTF8Encoding();
            var content = JsonConvert.SerializeObject(new { redirect_url = x.RedirectUri });
            byte[] bytes = encoding.GetBytes(content);

            x.Response.StatusCode = 200;
            x.Response.ContentLength = bytes.Length;
            x.Response.ContentType = "text/plain";
            x.Response.Body = new MemoryStream();

            await x.Response.WriteAsync(content);
            // at this point I see that x.Response.Body.Length == 470, but message states there are 0 of 470 written
        };
});
Run Code Online (Sandbox Code Playgroud)

有什么办法可以让它工作吗?

Ryt*_*s I 6

使用新的 C#using语法时也会发生这种情况:

using var ms = new MemoryStream();
using var writer = new StreamWriter(ms);
writer.WriteLine("my content");
memoryStream.Position = 0;
return File(ms, "text/plain");
Run Code Online (Sandbox Code Playgroud)

在这种情况下,在刷新MemoryStream之前访问StreamWriter。要么使用旧语法StreamWriter

using var ms = new MemoryStream();
using (var writer = new StreamWriter(ms, Encoding.UTF8, -1, true))
{
    writer.WriteLine("my content");
}
memoryStream.Position = 0;
return File(ms, "text/plain");
Run Code Online (Sandbox Code Playgroud)

或刷新作家:

using var ms = new MemoryStream();
using var writer = new StreamWriter(ms);
writer.WriteLine("my content");
writer.Flush();
memoryStream.Position = 0;
return File(ms, "text/plain");
Run Code Online (Sandbox Code Playgroud)

  • 这对我来说很有效``writer.Flush(); MemoryStream.Position = 0;``` (4认同)

pwr*_*imo 2

更改了代码以写入原始响应流,现在可以工作了。

facebookOptions.Events.OnRedirectToAuthorizationEndpoint =
    async (x) =>
    {
        var content = JsonConvert.SerializeObject(new { redirect_url = x.RedirectUri });

        x.Response.StatusCode = 200;
        x.Response.ContentType = "text/plain";

        await x.Response.WriteAsync(content);
    };
Run Code Online (Sandbox Code Playgroud)