ASP.NET Core中间件中渲染Razor视图

在中间件中执行完MVC的处理之后检查返回状态,如果是错误状态就直接渲染视图并输出

实现方式就是在Configure中注入ICompositeViewEngine实例,构造视图上下文,再渲染视图为字符串,最后输出。

第一种:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ICompositeViewEngine engine)
        {
            // 放到最后
            app.Use(async (context, next) =>
            {
                await next();
                if (context.Response.StatusCode == (int)HttpStatusCode.NotFound)
                {
                    context.Response.ContentType = "text/html";
                    var viewResult = engine.GetView("~/", "~/Views/Home/notfound.cshtml", true);
                    if (!viewResult.Success)
                    {
                        await context.Response.WriteAsync("连错误视图都找不到了。。");
                    }
                    using (var output = new StringWriter())
                    {
                        var metadataProvider = new EmptyModelMetadataProvider();
                        var viewData = new ViewDataDictionary(metadataProvider, new ModelStateDictionary());
                        viewData["Name"] = "fan";//ViewData传参
                        //视图上下文对于视图渲染来说很重要,视图中的前后台交互都需要它
                        var viewContext = new ViewContext()
                        {
                            HttpContext = context,
                            Writer = output,
                            RouteData = new Microsoft.AspNetCore.Routing.RouteData()
                            {
                                //RouteData在这里传入视图,这样视图可以显示错误信息之类的数据
                            },
                            View = viewResult.View,
                            ViewData = viewData,
                            FormContext = new FormContext(),
                            ActionDescriptor = new Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor()
                        };
                        //渲染
                        await viewResult.View.RenderAsync(viewContext);

                        //输出到响应体
                        await context.Response.WriteAsync(output.ToString());
                    }
                }
            });
        }

 

第二种:

var actionDescriptor = context.GetEndpoint()?.Metadata.GetMetadata<ControllerActionDescriptor>()
                                ?? new ControllerActionDescriptor();
            var routeData = context.GetRouteData() ?? new RouteData();
            var actionContext = new ActionContext();
            actionContext.HttpContext = context;
            actionContext.RouteData = routeData;
            actionContext.ActionDescriptor = actionDescriptor;
            var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), actionContext.ModelState);
            viewData.Model = new ErrorViewModel { RequestId = Activity.Current?.Id ?? context.TraceIdentifier, Exception = innerException, StatusCode = statusCode };
            string viewName = this._env.IsDevelopment() ? "Error" : "Home/Notfound";
            var viewResult = new PartialViewResult()
            {
                ViewName = viewName,//部分视图名
                ViewData = viewData
            };
            context.Response.StatusCode = statusCode;
            await viewResult.ExecuteResultAsync(actionContext);

 

第三种:(未测试)

            //var executor = context.RequestServices.GetRequiredService<IActionResultExecutor<PartialViewResult>>();
            //await executor.ExecuteAsync(actionContext, viewResult);

 

posted @ 2020-04-16 23:19  .Neterr  阅读(509)  评论(1编辑  收藏  举报