コード例 #1
0
        public static string Render <TModel>(this WebViewPage <TModel> view, HttpContextBase httpContext, TModel model = default(TModel))
        {
            var writer = new StringWriter();

            view.ViewData.Model = model;
            view.Initialize(httpContext, writer);

            var webPageContext = new WebPageContext(view.ViewContext.HttpContext, page: null, model: null);

            // Using private reflection to access some internals
            // Note: ideally we would not have to do this, but WebPages is just not mockable enough :(
            var dynamicPageContext = webPageContext.AsDynamic();

            dynamicPageContext.OutputStack.Push(writer);

            // Push some section writer dictionary onto the stack. We need two, because the logic in WebPageBase.RenderBody
            // checks that as a way to make sure the layout page is not called directly
            var sectionWriters = new Dictionary <string, SectionWriter>(StringComparer.OrdinalIgnoreCase);

            dynamicPageContext.SectionWritersStack.Push(sectionWriters);
            dynamicPageContext.SectionWritersStack.Push(sectionWriters);

            // Set the body delegate to do nothing
            dynamicPageContext.BodyAction = (Action <TextWriter>)(w => { });

            view.AsDynamic().PageContext = webPageContext;
            view.Execute();

            return(writer.ToString());
        }
コード例 #2
0
        public static string Render(this WebViewPage view, HttpContextBase httpContext, object model = null)
        {
            StringWriter writer = new StringWriter();

            view.Initialize(httpContext, writer);
            view.ViewData.Model = model;
            WebPageContext webPageContext = new WebPageContext(view.ViewContext.HttpContext, null, model);

            // Using private reflection to access some internals
            // Also make sure the use the same writer used for initializing the ViewContext in the OutputStack
            // Note: ideally we would not have to do this, but WebPages is just not mockable enough :(

            // Add the writer to the output stack
            PropertyInfo       outputStackProp = typeof(WebPageContext).GetProperty("OutputStack", BindingFlags.Instance | BindingFlags.NonPublic);
            Stack <TextWriter> outputStack     = (Stack <TextWriter>)outputStackProp.GetValue(webPageContext, null);

            outputStack.Push(writer);

            // Push some section writer dictionary onto the stack. We need two, because the logic in WebPageBase.RenderBody
            // checks that as a way to make sure the layout page is not called directly
            PropertyInfo sectionWritersStackProp = typeof(WebPageContext).GetProperty("SectionWritersStack", BindingFlags.Instance | BindingFlags.NonPublic);
            Stack <Dictionary <string, SectionWriter> > sectionWritersStack = (Stack <Dictionary <string, SectionWriter> >)sectionWritersStackProp.GetValue(webPageContext, null);
            Dictionary <string, SectionWriter>          sectionWriters      = new Dictionary <string, SectionWriter>(StringComparer.OrdinalIgnoreCase);

            sectionWritersStack.Push(sectionWriters);
            sectionWritersStack.Push(sectionWriters);

            // Set the body delegate to do nothing
            PropertyInfo bodyActionProp = typeof(WebPageContext).GetProperty("BodyAction", BindingFlags.Instance | BindingFlags.NonPublic);

            bodyActionProp.SetValue(webPageContext, (Action <TextWriter>)(w => { }), null);

            // Set the page context on the view (the property is public, but the setter is internal)
            PropertyInfo pageContextProp = typeof(WebPageRenderingBase).GetProperty("PageContext", BindingFlags.Instance | BindingFlags.Public);

            pageContextProp.SetValue(view, webPageContext, BindingFlags.NonPublic, null, null, null);

            // Execute/render the view
            view.Execute();

            return(writer.ToString());
        }