代码之家  ›  专栏  ›  技术社区  ›  ThomasArdal

使用ASP.NET核心中间件在HTML文件中插入脚本引用

  •  0
  • ThomasArdal  · 技术社区  · 6 年前

    this blog 发布并显示如下内容:

    public class MyMiddleware
    {
        private readonly RequestDelegate _next;
    
        public MyMiddleware(RequestDelegate next)
        {
            _next = next;
        }
    
        public async Task Invoke(HttpContext context)
        {
            var newContent = string.Empty;
            var existingBody = context.Response.Body;
    
            using (var newBody = new MemoryStream())
            {
                context.Response.Body = newBody;
    
                try
                {
                    await _next.Invoke(context);
                }
                finally
                {
                    context.Response.Body = existingBody;
                }
    
                newBody.Seek(0, SeekOrigin.Begin);
    
                newContent = new StreamReader(newBody).ReadToEnd();
    
                if (context.Response.ContentType.StartsWith("text/html"))
                {
                    newContent = newContent.Replace("</body", "<script src=\"my-reference-here\"></script></body");
                }
    
                await context.Response.WriteAsync(newContent);
            }
        }
    }
    

    这里的主要挑战是中间件对服务器的所有请求都运行,包括CSS、javascripts、favicons等。我希望它只对HTML输出运行,因为上面的代码会给某些文件类型带来问题,而且我不想将所有响应写两次。

    MapWhen ,但它似乎不支持查看响应的内容类型。

    2 回复  |  直到 6 年前
        1
  •  0
  •   poke    6 年前

    我个人推荐你 将其作为中间件实现。从您自己的实现中可以看到,您正在将整个响应读入内存,以便能够对其执行一些替换。这是非常低效的,并阻止你流的反应。 BrowserLink modifying the stream as it happens 这样效率会更高。

    但是您应该考虑将这个逻辑移到MVC中。当然,这假设您不需要修改静态文件内容。但是在MVC中,您可以编写 result filter 只有当 ViewResult 正在生成(即当呈现MVC视图时)。在该过滤器中,您可以修改视图结果以设置一些参数来注入该脚本。

    在MVC内部,我只需在布局中添加一个标记助手或某个部分,然后您就可以在其中呈现脚本标记。这样,您就可以保持对布局的完全控制,并将其与MVC很好地集成。

    Response.ContentType 更进一步,这样您就不会将响应读入内存流中,以获得不需要修改的响应。

        2
  •  0
  •   Dzianis Yafimau    6 年前

    我建议您在视图中使用节。只需在布局中实现这一点:

    @RenderSection("BottomScripts", required: false)
    

    在您的视图中,可以使用以下内容:

    @section BottomScripts {
     @if (Model.NeedThisScript)
     {
      await Html.RenderPartialAsync("PartialWithYourScripts");
     }
    }