asp.net-core - 希望 ASP.NET Core 中间件在 MVC Razor View Engine 之后运行

标签 asp.net-core asp.net-core-middleware

我希望在 MVC Razor View Engine 处理数据后在 ASP.NET Core 中运行中间件模块。我可以让它运行,但它似乎没有收集所有数据。我有一个标记帮助程序,可以更新 DI 对象的集合,但是当中间件运行时,DI 对象的集合为空。我的startup.cs看起来像这样:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    { 
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

        app.UseMiddleware<MyMiddleware>();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }

我的中间件是这样的:

public class MyMiddleware
{
    private readonly RequestDelegate nextMiddleware;
    private readonly IScriptManager _scriptManager;

    public MyMiddleware(RequestDelegate next, IScriptManager scriptManager)
    {
        this.nextMiddleware = next;
        _scriptManager = scriptManager;
    }

    public async Task Invoke(HttpContext context)
    {
        var cnt = _scriptManager.ScriptTexts.Count;
        .. get HTML
        Stream originalStream = context.Response.Body;
        ...
        .. update HTML
        await context.Response.WriteAsync(htmlData);

我确实得到了我想要的 HTML,但我的 DI 中的集合似乎没有更新。

*** 注释 - 可能但不起作用的结果过滤器

        services.AddMvc(options =>
        {
            options.Filters.Add(new AppendToHtmlBodyFilter());
        });

public class AppendToHtmlBodyFilter : TypeFilterAttribute
{
    private readonly IScriptManager _scriptManager;

    public AppendToHtmlBodyFilter():base(typeof(SampleActionFilterImpl))
    {
    }

    private class SampleActionFilterImpl : IResultFilter
    {
        private readonly IScriptManager _scriptManager;

        public SampleActionFilterImpl(IScriptManager scriptManager)
        {
            _scriptManager = scriptManager;
            //_logger = loggerFactory.CreateLogger<SampleActionFilterAttribute>();
        }

        public void OnResultExecuted(ResultExecutedContext context)
        {
            var cnt = _scriptManager.ScriptTexts.Count;
            Stream originalStream = context.HttpContext.Response.Body;
            using (MemoryStream newStream = new MemoryStream())
            {
                context.HttpContext.Response.Body = newStream;
                context.HttpContext.Response.Body = originalStream;
                newStream.Seek(0, SeekOrigin.Begin);
                StreamReader reader = new StreamReader(newStream);
                var htmlData = reader.ReadToEnd();

最佳答案

据我所知,在请求管道中的 mvc 之后无法运行中间件。如果您想操纵 Razor 输出,可以使用过滤器。结果过滤器似乎适合您的情况。

Result filters are ideal for any logic that needs to directly surround view execution or formatter execution. Result filters can replace or modify the action result that's responsible for producing the response.

查看官方文档 https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters#result-filters

另请参阅如何通过过滤器使用依赖项注入(inject) https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters#dependency-injection

更新

我无法让它与结果过滤器一起工作(它可以工作 json 结果,但不能工作 viewresult)。

但是我发现了一个很好的中间件示例:http://www.mikesdotnetting.com/article/269/asp-net-5-middleware-or-where-has-my-httpmodule-gone

public class MyMiddleware
{
    private readonly RequestDelegate nextMiddleware;
    private readonly IScriptManager _scriptManager;

    public MyMiddleware(RequestDelegate next, IScriptManager scriptManager)
    {
       this.nextMiddleware = next;
       _scriptManager = scriptManager;
    }
    public async Task Invoke(HttpContext context)
    {
       var cnt = _scriptManager.ScriptTexts.Count;
        using (var memoryStream = new MemoryStream())
        {
            var bodyStream = context.Response.Body;
            context.Response.Body = memoryStream;

            await _next(context);

            var isHtml = context.Response.ContentType?.ToLower().Contains("text/html");
            if (context.Response.StatusCode == 200 && isHtml.GetValueOrDefault())
            {
                    memoryStream.Seek(0, SeekOrigin.Begin);
                    using (var streamReader = new StreamReader(memoryStream))
                    {
                        var responseBody = await streamReader.ReadToEndAsync();
                        // update html
                        using (var amendedBody = new MemoryStream())
                        using (var streamWriter = new StreamWriter(amendedBody))
                        {
                            streamWriter.Write(responseBody);
                            amendedBody.Seek(0, SeekOrigin.Begin);
                            await amendedBody.CopyToAsync(bodyStream);
                        }
                    }
            }
        }
    }
}

关于asp.net-core - 希望 ASP.NET Core 中间件在 MVC Razor View Engine 之后运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40582320/

相关文章:

c# - 有什么方法可以在没有 Debug模式的情况下运行 .net 核心 Web 应用程序?

asp.net-core - 登录和注销后 MVC 6 中的后退按钮问题

azure - 如何从 Azure Key Vault 获取所有 secret ,然后使用 ASP.Net Core 加载到配置对象中

c# - asp.net core中间件如何做DI?

c# - ASP.Net Core异常处理中间件

c# - 如何手动反序列化 ModelStateDictionary

asp.net-mvc - 构建面向完整 .net 框架的 VS2017 .net core 应用程序

c# - 'UseAuthentication()' 到底是做什么用的?

c# - 如何配置多个异常处理程序

c# - 在使用 MapWhen 进行分支时注册中间件,以便仅为一组端点运行它