【问题标题】:ASP.NET MVC - Modifying view result in OnActionExecutedASP.NET MVC - 在 OnActionExecuted 中修改视图结果
【发布时间】:2017-01-12 22:18:15
【问题描述】:

我有一个 ASP.NET MVC 控制器,其中包含一组返回 ViewResult 的操作方法。现在,我需要能够通过以下方式根据某个 URL 参数更改操作的结果:

  • 如果参数不存在,则原样返回ViewResult
  • 如果参数存在,则从刚刚执行的操作中获取ViewResult,将视图呈现为字符串,并返回包含此字符串(原始 HTML)+ 一些附加信息(与问题)

我试图通过在我的控制器中覆盖 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

如何在此处将视图呈现为字符串?

【问题讨论】:

  • 为什么不直接从 ActionResult 返回一个字符串?
  • @JordyvanEijk,因为我的控制器中有很多操作需要实现相同的逻辑。我想用一种方法完成所有操作。
  • 只需创建一个可以完成所有工作的方法并从每个操作中调用该方法。并让该方法返回字符串或 ContentResult 之类的内容...
  • @JordyvanEijk,我所说的“很多”是指 50 多种方法。你的建议不是很方便。有没有办法使用动作过滤器来做到这一点?

标签: c# asp.net-mvc


【解决方案1】:

viewResult.View 仅在视图结果在控制器上下文中执行时才会填充(请参阅MVC source code 中的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();
    }
}

【讨论】:

    猜你喜欢
    • 2019-06-10
    • 1970-01-01
    • 2014-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-13
    • 1970-01-01
    相关资源
    最近更新 更多