HttpResponse.Filter 在 MVC 6/vNext 中?

HttpResponse.Filter in MVC 6 / vNext?

我正在开发一个网站框架,该框架使用 "Widgets" 在 portal/portlet 类型的网站内呈现内容块。基本上是 Wordpress 如何让您自定义网站的一个非常简短的版本。

经过搜索但未能找到任何现有框架,看来最合理的实现方式是使用 MVC 的 "Partial Views" 功能。

我希望能够完全封装每个 "widget" 而不必在宿主视图中重复脚本或样式标签(视图不需要知道任何有关如何呈现小部件的信息)。

为实现这一点,任何脚本引用都由 Widget Partial View 存储,然后在 View 呈现其自己的脚本部分时注入。在一个实例中,这是使用响应过滤器实现的。

我正在通过 CoreCLR 使用 MVC 6 (vNext),并且正在尝试确定如何在新框架下实现此过滤器位。似乎 HttpResponse 对象不再具有 "Filter" 字段。

你能告诉我这在新框架下如何运作吗?

/// <summary>
/// Appends partial view scripts to the html response of an AJAX request
/// </summary>
public class RenderAjaxPartialScriptsAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            var response = filterContext.HttpContext.Response;
            if (response.Filter != null)
            response.Filter = new RenderAjaxPartialScriptsResponseFilter(response.Filter, filterContext);
        }
    }
}

原始代码来自 Ryan Burnham 的博客 https://rburnham.wordpress.com/2015/03/13/asp-net-mvc-defining-scripts-in-partial-views/#comment-2286

您可以通过在 Startup.cs 中使用 Middleware 来实现:

快捷方式:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        //// 

        app.Use(async (httpContext, next) =>
        {
            await next();

            // if is ajax request
            if (httpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
            {
                // if succesful status code
                if (httpContext.Response.StatusCode == 200)
                {
                    // you can get scripts data from httpContext.Items[key] and build html
                    string html = "<script src='~/js/script-demo.js'></script>";

                    using (var writeResponseStream = new StreamWriter(httpContext.Response.Body))
                    {
                        // write html to response body
                        await writeResponseStream.WriteAsync(html);
                    }
                }
            }
        });

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

正确的方法:

中间件实现:

    public class AjaxScriptInjectorMiddleware
    {
        private readonly RequestDelegate _next;

        public AjaxScriptInjectorMiddleware(RequestDelegate next)
        {
                _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            await _next.Invoke(context);

            // if is ajax request
            if (IsAjax(context.Request))
            {
                // if succesful status code
                if (IsSuccess(context.Response.StatusCode))
                {
                    // you can get scripts data from context.Items[key] and build html
                    string html = "<script src='~/js/script-demo.js'></script>";

                    using(var writeResponseStream = new StreamWriter(context.Response.Body))
                    {
                        // write html to response body
                        await writeResponseStream.WriteAsync(html);
                    }
                }
            }
        }

        private bool IsAjax(HttpRequest request)
        {
                return request.Headers["X-Requested-With"] == "XMLHttpRequest";
        }

        private bool IsSuccess(int statusCode)
        {
                return statusCode >= 200 && statusCode <= 299;
        }
   }

IApplicationBuilder扩展方法:

public static class AjaxScriptInjectorExtensions
{
    public static IApplicationBuilder UseAjaxScriptInjector(this IApplicationBuilder builder)
    {
            return builder.UseMiddleware<AjaxScriptInjectorMiddleware>();
    }
}

使用middleware:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
     // use custom ajax script injector middleware
     app.UseAjaxScriptInjector();

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