【问题标题】:ASP.NET MVC not rendering custom display templates when rendering view as a string将视图呈现为字符串时,ASP.NET MVC 不呈现自定义显示模板
【发布时间】:2013-05-29 17:14:04
【问题描述】:

我需要在我的应用程序中呈现一个特定的 MVC 视图(对于几百个数据库记录 - 每条记录呈现一个视图),每个视图都呈现为一个字符串,以便我可以将它们保存到 *.html 文件以供离线查看。

我找到了几个关于如何做到这一点的资料:

How to render an ASP.NET MVC ViewResult to HTML?

http://www.west-wind.com/weblog/posts/2012/May/30/Rendering-ASPNET-MVC-Views-to-String

这似乎只适用于基本视图。我的问题是我的视图调用了 Html.DisplayFor(它呈现了我的自定义显示模板),而这些模板也调用了 Html.DisplayFor。当我使用上面链接中的方法时,似乎正在使用默认显示模板,并且没有为我的视图的这些区域呈现我的 HTML。

请注意,当让 MVC 将它们呈现为 ViewResult 并在屏幕上显示它们时,我试图以字符串形式呈现的视图可以使用自定义显示模板很好地呈现。

有没有办法将 MVC 视图呈现为字符串,以便可以将其保存到使用自定义显示模板而不是默认显示模板的文件中?我不希望为此专门创建一个不包含自定义显示模板的新视图。非常感谢任何帮助。

这是我的代码示例,仅显示最基本的功能。同样,这适用于基本视图,但不适用于我的自定义显示模板。

public void GenerateOfflinePackage(IndexViewModel model, ControllerContext controllerContext)
{
    var folderName = Guid.NewGuid().ToString();
    var tempPackagePath = string.Format("{0}\\{1}", this.hostingEnvironmentWrapper.MapPath("~/App_Data"), folderName);

    Directory.CreateDirectory(tempPackagePath);

    var cpfModel = this.careerPlanningFormService.BuildSummaryViewModel(59);
    var viewString = this.RenderRazorViewToString("~/Views/CPF/Summary.cshtml", cpfModel, controllerContext);

    using (StreamWriter outfile = new StreamWriter(tempPackagePath + @"\59.html", true))
    {
        outfile.Write(viewString);
    }
}

public string RenderRazorViewToString(string viewName, object model, ControllerContext ctxt)
{
    var s = string.Empty;
    var viewData = ctxt.Controller.ViewData;
    var tempData = ctxt.Controller.TempData;

    viewData.Model = model;

    using (var sw = new StringWriter())
    {
        var viewResult = ViewEngines.Engines.FindPartialView(ctxt, viewName);
        var viewContext = new ViewContext(ctxt, viewResult.View, viewData, tempData, sw);
        viewResult.View.Render(viewContext, sw);
        viewResult.ViewEngine.ReleaseView(ctxt, viewResult.View);
        s = sw.GetStringBuilder().ToString();
    }

    return s;
}

ViewModel 示例和一些包含的类:

    public class SummaryViewModel : CareerPlanningFormBase
{
    public string StaffName { get; set; }

    public string StaffImageUrl { get; set; }

    public string PredominantRole { get; set; }

    public IList<SummaryResultsMeasuresSectionModel> ResultsMeasuresSections { get; set; }
}

public class SummaryResultsMeasuresSectionModel
{
    public string SectionName { get; set; }

    public string SectionLabelTitle { get; set; }

    public string SectionLabelText { get; set; }

    public IList<SummaryResultsMeasureModel> ResultsMeasures { get; set; }
}

public class SummaryResultsMeasureModel
{
    public string ResultsMeasureName { get; set; }

    public IEnumerable<string> MeasureTypes { get; set; }

    public IList<SummaryResultsMeasureCriterionModel> ResultsMeasureCriteria { get; set; }

    public IEnumerable<SummaryActionPlanModel> ActionPlans { get; set; }
}

【问题讨论】:

    标签: c# asp.net asp.net-mvc


    【解决方案1】:

    如果我是你,我会采取不同的方法。执行子操作方法输出缓存,然后创建一个自定义缓存提供程序,用于保存到磁盘并从磁盘读取。通过这种方式,您可以获取渲染输出并将其存储到磁盘。我有一篇博文可以引导您完成它。

    http://www.haneycodes.net/custom-output-caching-with-mvc3-and-net-4-0-done-right

    【讨论】:

    • 我可能遗漏了一些东西,但我不明白这会有什么帮助。我不是在每页/每个请求的基础上这样做的。我正在单击一个按钮并调用一个方法,该方法将遍历数百条记录,并为每条记录呈现一个视图并将生成的 HTML 保存为文件。最终产生了几百个 HTML 文件——全部在一个请求中。最终的结果是应用程序将生成一个链接到所有这些文件的索引文件,所有这些文件都将被压缩并提供给用户,以便在旅行和离线(即飞行中)时查看数据。这是最容易的部分。
    • 生成的视图 - 它来自控制器上的 ActionResult / ActionMethod 吗?
    • 生成离线包的用户将单击管理屏幕上的按钮。处理 POST 的控制器操作方法将对 GenerateOfflinePackage 进行服务方法调用。该方法将完成所有工作,生成视图,保存它们等(请参阅我的原始帖子以获取仅执行一条记录的示例)。处理 POST 的控制器,在服务方法完成后,只是为用户做一个重定向。
    • 如果你说你的动作方法产生了很多输出/保存,那么输出缓存可能对你没有多大帮助。
    • 是的,这是正确的,它确实有很多。不过,感谢您的帮助。
    猜你喜欢
    • 2016-10-10
    • 2011-01-28
    • 1970-01-01
    • 2011-06-23
    • 2013-09-28
    相关资源
    最近更新 更多