Asp.Net Core 2 中是不是有等效于“HttpContext.Response.Write”的内容?

Posted

技术标签:

【中文标题】Asp.Net Core 2 中是不是有等效于“HttpContext.Response.Write”的内容?【英文标题】:Is there an equivalent to "HttpContext.Response.Write" in Asp.Net Core 2?Asp.Net Core 2 中是否有等效于“HttpContext.Response.Write”的内容? 【发布时间】:2018-05-01 05:08:05 【问题描述】:

我正在尝试使用 Asp.Net Core 2 中的 ActionFilter 在页面上附加一些 htmljavascript 内容。

在 MVC 中,它正在使用

 filterContext.HttpContext.Response.Write(stringBuilder.ToString());

但在 Core 中它不起作用。

我试图用这个来实现:

filterContext.HttpContext.Response.WriteAsync(stringBuilder.ToString());

但它会使整个页面变为空白。

我正在寻找构建于 Asp.Core 2.0 中的 nopCommerce 4.0 解决方案

【问题讨论】:

【参考方案1】:

静态和异步方法HttpResponseWritingExtensions.WriteAsync是目前实现这一目标的首选方式。

目前,您可以在程序集Assembly Microsoft.AspNetCore.Http.Abstractions中找到它。

using Microsoft.AspNetCore.Http;

[HttpGet("test")]
public async Task GetTest()
    => await HttpResponseWritingExtensions.WriteAsync(this.Response, "Hello World");

2022 年 2 月 23 日更新

与主题有点相关。使用 ASP.NET Core 6.0,您可以使用 Minimal API 编写一个简单的响应,如下所示:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World");
app.Run();

Source: MSDN

【讨论】:

【参考方案2】:

Response.Body.Write 将字节数组作为参数。

public void OnGet() 
    var text = "<h1>Hello, Response!</h1>";
    byte[] data = System.Text.Encoding.UTF8.GetBytes(text);
    Response.Body.Write(data, 0, data.Length);

或异步版本:

public async Task OnGetAsync() 
    var text = "<h1>Hello, Async Response!</h1>";
    byte[] data = System.Text.Encoding.UTF8.GetBytes(text);
    await Response.Body.WriteAsync(data, 0, data.Length);

【讨论】:

确保从 razor 页面中删除或评论我们的默认内容,因为 Response.Body.Write 接管页面响应 ` @* @section Scripts @await Html.RenderPartialAsync("_ValidationScriptsPartial"); *@`【参考方案3】:

你可以试试这样的

INopStartup.Configure(IApplicationBuilder 应用程序)的自定义实现中

application.Use(async (context, next) =>    

    using (var customStream = new MemoryStream())
    
        // Create a backup of the original response stream
        var backup = context.Response.Body;

        // Assign readable/writeable stream
        context.Response.Body = customStream;

        await next();

        // Restore the response stream
        context.Response.Body = backup;

        // Move to start and read response content
        customStream.Seek(0, SeekOrigin.Begin);
        var content = new StreamReader(customStream).ReadToEnd();

        // Write custom content to response
        await context.Response.WriteAsync(content);
    
);

比在你的自定义 ResultFilterAttribute

public class MyAttribute : ResultFilterAttribute

    public override void OnResultExecuted(ResultExecutedContext context)
    
        try
        
            var bytes = Encoding.UTF8.GetBytes("Foo Bar");

            // Seek to end
            context.HttpContext.Response.Body.Seek(context.HttpContext.Response.Body.Length, SeekOrigin.Begin);
            context.HttpContext.Response.Body.Write(bytes, 0, bytes.Length);
        
        catch
        
            // ignored
        

        base.OnResultExecuted(context);
    

结果

希望这有助于进入正确的道路。

【讨论】:

如果我们在 nopCommerce 中使用这个解决方案,我们就会遇到问题。在INopStartup.Configure方法中,如果我们先调用await next()然后恢复响应流,它不会加载图片和脚本用户端报错 Response Content-Length mismatch:too many byteswritten. 如果我们先恢复响应流然后调用 await next() 那么它会在 filterContext.HttpContext 报错.Response.Body.Seek() 方法未找到.【参考方案4】:

我的代码没有为异步执行做好准备,所以我使用了:

Response.WriteAsync("text").Wait();

.Wait() 使执行等待异步方法完成执行以继续。

不知道性能是不是最好,但已经比.Net Framework方案好

.Wait(): https://docs.microsoft.com/pt-br/dotnet/api/system.io.stream.writeasync?view=net-6.0

.WriteAsync():https://docs.microsoft.com/pt-br/dotnet/api/system.threading.tasks.task.wait?view=net-6.0

【讨论】:

以上是关于Asp.Net Core 2 中是不是有等效于“HttpContext.Response.Write”的内容?的主要内容,如果未能解决你的问题,请参考以下文章

与 Request.RequestURI 等效的 ASP.NET Core MVC 是啥?

Rails 世界中是不是有与 ASP.NET Web API 等效的工具?

通过 IIS ARR 的客户端关联/粘性会话是不是适用于 ASP.NET Core 3+/.NET 5?

在 ASP.NET MVC 中是不是有等价于 redirect_to :back

.Net Core DebugDiag 等效

适用于 ASP.NET 开发者的 ASP.NET Core