ASP.NET MVC - изменение результата отображения в OnActionExecuted

У меня есть ASP.NET MVC-контроллер с кучей методов действий, возвращающих ViewResult. Теперь мне нужно изменить результат действия на основе определенного параметра URL следующим образом:

  • Если параметр отсутствует, просто верните ViewResult поскольку он
  • Если параметр присутствует, возьмите ViewResult из только что выполненного действия, визуализируйте представление в строку и верните FileStreamResult содержащую эту строку (необработанный 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.

Как я могу визуализировать представление в строке здесь?

+1
05 сент. '16 в 14:06
источник поделиться
1 ответ

viewResult.View заполняется только тогда, когда результат представления выполняется в контексте контроллера (см. метод ExecuteResult в исходном коде MVC). Метод 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();
    }
}
+1
06 сент. '16 в 9:53
источник

Посмотрите другие вопросы по меткам или Задайте вопрос