ASP.NET MVC - 在OnActionExecuted中修改视图结果
ASP.NET MVC - 在OnActionExecuted中修改视图结果
我有一个ASP.NET MVC控制器,其中有许多返回ViewResult的操作方法。现在,我需要根据某个特定的URL参数能够按以下方式更改操作结果:
- 如果未出现参数,则只需返回原始的
ViewResult
- 如果出现了参数,则从刚刚执行的操作中获取
ViewResult
,将视图渲染为字符串,并返回包含此字符串(原始HTML)+一些其他信息(与问题无关)的FileStreamResult
我试图通过在我的控制器中覆盖 OnActionExecuted
来实现此操作:
protected override void OnActionExecuted(ActionExecutedContext filterContext) { base.OnActionExecuted(filterContext); var viewResult = filterContext.Result as ViewResult; if (viewResult != null /* && certain URL param present*/) { string rawHtml = RenderViewIntoString(viewResult); filterContext.Result = new FileStreamResult(new MemoryStream(Encoding.UTF8.GetBytes(rawHtml)), "application/octet-stream"); } }
但是我找不到一种方法来实现 RenderViewIntoString
,因为由于某种原因,在这里 viewResult.View
是 null
。
我该如何在此处将视图渲染为字符串?
admin 更改状态以发布 2023年5月21日
viewResult.View
只有在控制器的上下文中执行视图结果时才会填充(请参见MVC源代码中的ExecuteResult
方法)。方法OnActionExecuted
在管道中较早调用,这就是为什么在您的情况下viewResult.View
为null
的原因。
您需要手动使用ViewEngineCollection
找到视图,然后呈现它:
private static string RenderViewIntoString(ViewResult viewResult, ActionExecutedContext filterContext) { string viewName = !string.IsNullOrEmpty(viewResult.ViewName) ? viewResult.ViewName : filterContext.ActionDescriptor.ActionName; IView view = viewResult.ViewEngineCollection.FindView(filterContext.Controller.ControllerContext, viewName, viewResult.MasterName).View; if (view == null) { throw new InvalidOperationException($"The view '{viewName}' or its master was not found"); } using (var stringWriter = new StringWriter()) { var viewContext = new ViewContext(filterContext.Controller.ControllerContext, view, filterContext.Controller.ViewData, filterContext.Controller.TempData, stringWriter); view.Render(viewContext, stringWriter); return stringWriter.ToString(); } }