ASP.NET MVC - 在OnActionExecuted中修改视图结果

17 浏览
0 Comments

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.Viewnull

我该如何在此处将视图渲染为字符串?

admin 更改状态以发布 2023年5月21日
0
0 Comments

viewResult.View只有在控制器的上下文中执行视图结果时才会填充(请参见MVC源代码中的ExecuteResult方法)。方法OnActionExecuted在管道中较早调用,这就是为什么在您的情况下viewResult.Viewnull的原因。

您需要手动使用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();
    }
}

0