将视图渲染为字符串性能

时间:2013-08-02 01:34:40

标签: string asp.net-mvc-4

我构建了一个应用程序,可以将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;
        }

2 个答案:

答案 0 :(得分:0)

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

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();
            }
        }
    }

答案 1 :(得分:0)

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