2016-11-14 104 views
2

我想在MVC Razor View Engine處理完數據後在ASP.NET Core中運行MiddleWare模塊。我可以讓它運行,但它似乎沒有收集所有的數據。我有一個標籤助手來更新DI對象的集合,但是當中間件運行時,DI對象的集合是空的。我startup.cs看起來是這樣的:想要ASP.NET Core中間件在MVC Razor View Engine後運行

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

回答

3

據我所知是沒有辦法在請求管道MVC後運行一箇中間件。如果你想操縱剃刀輸出,你可以使用過濾器。結果過濾器似乎適合您的情況。

結果過濾器非常適合任何需要直接環繞 視圖執行或格式化程序執行的邏輯。結果過濾器可以替換或修改負責生成響應的操作結果。

參見官方文檔https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters#result-filters

也看到如何使用依賴注入過濾https://docs.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); 
         } 
        } 
      } 
     } 
    } 
} 
+0

喜@ademcaglin和感謝。我已經編寫了一個OnResultExecuted過濾器,但我沒有在我的htmlData處理過的剃刀html(我得到空字符串)。我如何編寫一個捕獲和更新由剃刀處理的html的動作過濾器?我不清楚過濾器在哪裏執行,以及如何將我的地址放在可以捕獲html並更新它的地方。我更新問題與「可能的但不工作的過濾器代碼」。 –

+0

你說得對。它似乎不適用於剃鬚刀輸出。不過,我發現了一箇中間件方法的解決方案,並按預期工作。查看我的更新。 –

相關問題