13

I'm trying to append some HTML and Javascript content on page using ActionFilter in Asp.Net Core 2.

In MVC, it's working with

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

but in Core it not working.

I tried to implement with this:

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

But it make complete page to blank.

I'm looking solution for nopCommerce 4.0 which build in Asp.Core 2.0

ˈvɔlə
  • 9,204
  • 10
  • 63
  • 89
Raju Paladiya
  • 778
  • 2
  • 12
  • 35

4 Answers4

19

The static and asynchronous method HttpResponseWritingExtensions.WriteAsync is currently the preferred way of reaching this goal.

Currently, you can find it in the assembly Assembly Microsoft.AspNetCore.Http.Abstractions.

using Microsoft.AspNetCore.Http;

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

UPDATE 2022-02-23

A little bit related to the topic. Using the ASP.NET Core 6.0 you can write a simple response using Minimal API like this:

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

Source: MSDN

ˈvɔlə
  • 9,204
  • 10
  • 63
  • 89
10

Response.Body.Write takes a byte array as an argument.

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

or async version:

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);
}
dragansr
  • 417
  • 6
  • 8
  • Make sure to remove or comment our default content from razor page, since Response.Body.Write takes over page response ` @* @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} } *@` – dragansr Nov 18 '17 at 22:24
4

You can try something like this

In a custom implementation of INopStartup.Configure(IApplicationBuilder application)

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);
    }
});

And than in your custom 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);
    }
}

And the result

Result HTML

Hope this helps to get into the right way.

Raphael
  • 990
  • 1
  • 13
  • 24
  • If we use this solution in nopCommerce, we are getting issue. In _INopStartup.Configure_ method, If we call **await next()** first and then **restore the response stream**, it will not load images and scripts on User side and gives error of **Response Content-Length mismatch:too many bytes written.** If we first restore the response stream and then call await next() then it will give error in **filterContext.HttpContext.Response.Body.Seek() method not found**. – Raju Paladiya Nov 20 '17 at 12:19
1

My code was no prepared for async execution, so i used:

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

.Wait() make the execution waits for the Async Method complete execution to continue.

I don't know if the performance is the best, but is already better than .Net Framework solution

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

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

Comth
  • 31
  • 2