1

我已经构建了一个将 mvc 视图呈现为字符串并使用 HiQPDF 呈现 PDF 报告的应用程序。这很好用,但是,重复调用 IView.Render 会导致相当大的性能下降。每次调用都比前一次调用长约 1 秒 - 并且呈现的 html 几乎相同。

任何人都知道其他不会影响这种性能的 html 渲染方法吗?任何人都知道为什么我看到这段代码的性能如此糟糕?

protected string RenderViewToStringInternal(string viewPath, object model,
                                                    bool partial = false,
                                                    string master = null)
        {
            //Find cached view 
            ViewEngineResult viewEngineResult = _cachedViews.ContainsKey(viewPath) ? _cachedViews[viewPath] : null;

            if (viewEngineResult == null)
            {
                //Get view engine result
                if (partial)
                    viewEngineResult = ViewEngines.Engines.FindPartialView(Context, viewPath);
                else
                    viewEngineResult = ViewEngines.Engines.FindView(Context, viewPath, master);

                if (viewEngineResult != null)
                {
                    _cachedViews.Add(viewPath, viewEngineResult);
                }
            }

            if (viewEngineResult == null)
                throw new FileNotFoundException("View not found");

            // get the view and attach the model to view data
            var view = viewEngineResult.View;

            Context.Controller.ViewData.Model = model;

            string result = null;

            using (var sw = new StringWriter())
            {
                var ctx = new ViewContext(Context, view,
                                            Context.Controller.ViewData,
                                            Context.Controller.TempData,
                                            sw);

                DateTime start = DateTime.Now;
                **view.Render(ctx, sw);** //This line's performance degrades after subsequent calls with similar data
                DateTime end = DateTime.Now;

                Logging.LogInformation(Logging.TraceType.UI, string.Format("ViewRenderer.RenderViewToStringInternal view.Render execution time: {0}", end.Subtract(start).TotalSeconds));

                viewEngineResult.ViewEngine.ReleaseView(Context, view);

                result = sw.ToString();
            }

            return result;
        }
4

2 回答 2

1

我正在使用以下内容将视图呈现为字符串,并且没有看到您描述的任何问题

public static class ContollerContextExtensions
    {
        /// <remarks>If you have any validation summaries they will not be populated by this method</remarks>
        public static string RenderPartialToString(this ControllerContext ControllerContext, string viewName, object model)
        {
            if (string.IsNullOrEmpty(viewName))
                viewName = ControllerContext.RouteData.GetRequiredString("action");
            ViewDataDictionary ViewData = new ViewDataDictionary();
            TempDataDictionary TempData = new TempDataDictionary();
            ViewData.Model = model;

            using (StringWriter sw = new StringWriter())
            {
                ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
                ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
                viewResult.View.Render(viewContext, sw);

                return sw.GetStringBuilder().ToString();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ControllerContext"></param>
        /// <param name="viewName"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        /// <remarks>If you have any validation summaries they will not be populated by this method</remarks>
        public static string RenderViewToString(this ControllerContext ControllerContext, string viewName, object model, string masterName = null)
        {
            if (string.IsNullOrEmpty(viewName))
                viewName = ControllerContext.RouteData.GetRequiredString("action");
            ViewDataDictionary ViewData = new ViewDataDictionary();
            TempDataDictionary TempData = new TempDataDictionary();
            ViewData.Model = model;

            using (StringWriter sw = new StringWriter())
            {
                ViewEngineResult viewResult = ViewEngines.Engines.FindView(ControllerContext, viewName, masterName);
                ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
                viewResult.View.Render(viewContext, sw);

                return sw.GetStringBuilder().ToString();
            }
        }
    }
于 2013-08-02T05:30:04.923 回答
0

正如我对我自己的问题的评论中所述 - 这个问题只发生在虚拟环境中。我从来没有确定为什么这段代码运行缓慢,但是为了解决我的性能问题,我更改了代码以通过呈现单个 MVC 部分的单独 Web 请求检索每个 PDF 页面。这显着提高了吞吐量,生成的请求不到 100 毫秒。

于 2014-01-13T17:17:44.850 回答