Желание, чтобы ПО промежуточного слоя ASP.NET Core запускалось после MVC Razor View Engine

Я хочу, чтобы модуль MiddleWare работал в ASP.NET Core после того, как MVC Razor View Engine обработал данные. Я могу запустить его, но, похоже, он собрал не все данные. У меня есть помощник по тегам, который обновляет коллекцию объекта 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();

person Peter Kellner    schedule 14.11.2016    source источник


Ответы (1)


Насколько я знаю, нет возможности запустить промежуточное ПО после 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);
                        }
                    }
            }
        }
    }
}
person adem caglin    schedule 14.11.2016
comment
привет @ademcaglin и спасибо. Мне удалось написать фильтр OnResultExecuted, но я не получаю в моем htmlData обработанный HTML-код бритвы (я получаю пустую строку). Как я могу написать фильтр действий, который захватывает и обновляет HTML, обрабатываемый бритвой? Мне непонятно, где выполняются фильтры и как поместить мой в место, где я могу захватывать html и обновлять его. Я обновил по вопросу Возможный, но не работающий код фильтра. - person Peter Kellner; 14.11.2016
comment
Ты прав. Похоже, это не работает для вывода бритвы. Однако я нашел решение для подхода к промежуточному программному обеспечению, и оно сработало, как ожидалось. Смотрите мое обновление. - person adem caglin; 15.11.2016