/// <inheritdoc />
        public void Activate(IRazorPage page, ViewContext context)
        {
            if (page == null)
            {
                throw new ArgumentNullException(nameof(page));
            }

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (page is Page)
            {
                return;
            }

            var activationInfo = _activationInfo.GetOrAdd(page.GetType(),
                                                          CreateViewActivationInfo);

            context.ViewData = CreateViewDataDictionary(context, activationInfo);

            for (var i = 0; i < activationInfo.PropertyActivators.Length; i++)
            {
                var activateInfo = activationInfo.PropertyActivators[i];
                activateInfo.Activate(page, context);
            }
        }
        /// <inheritdoc />
        public void Activate(IRazorPage page, ViewContext context)
        {
            if (page == null)
            {
                throw new ArgumentNullException(nameof(page));
            }

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var pageType = page.GetType();
            RazorPagePropertyActivator propertyActivator;

            if (!_activationInfo.TryGetValue(pageType, out propertyActivator))
            {
                // Look for a property named "Model". If it is non-null, we'll assume this is
                // the equivalent of TModel Model property on RazorPage<TModel>.
                //
                // Otherwise if we don't have a model property the activator will just skip setting
                // the view data.
                var modelType = pageType.GetRuntimeProperty(ModelPropertyName)?.PropertyType;
                propertyActivator = new RazorPagePropertyActivator(
                    pageType,
                    modelType,
                    _metadataProvider,
                    _propertyAccessors);

                propertyActivator = _activationInfo.GetOrAdd(pageType, propertyActivator);
            }

            propertyActivator.Activate(page, context);
        }
        async Task <ViewBufferTextWriter> RenderPageAsync(IViewBufferScope bufferScope, IRazorPage page, ViewRenderingContext viewRenderingContext)
        {
            var writer = viewRenderingContext.Writer as ViewBufferTextWriter;

            if (writer == null)
            {
                // If we get here, this is likely the top-level page (not a partial) - this means
                // that context.Writer is wrapping the output stream. We need to buffer, so create a buffered writer.
                var buffer = new ViewBuffer(bufferScope, page.GetType().AssemblyQualifiedName, ViewBuffer.ViewPageSize);
                writer = new ViewBufferTextWriter(buffer, viewRenderingContext.Writer.Encoding, this.htmlEncoder, viewRenderingContext.Writer);
            }
            else
            {
                // This means we're writing something like a partial, where the output needs to be buffered.
                // Create a new buffer, but without the ability to flush.
                var buffer = new ViewBuffer(bufferScope, page.GetType().AssemblyQualifiedName, ViewBuffer.ViewPageSize);
                writer = new ViewBufferTextWriter(buffer, viewRenderingContext.Writer.Encoding);
            }

            // The writer for the body is passed through the ViewContext, allowing things like HtmlHelpers
            // and ViewComponents to reference it.
            var oldWriter = viewRenderingContext.Writer;

            //var oldFilePath = context.ExecutingFilePath;

            viewRenderingContext.Writer = writer;
            //context.ExecutingFilePath = page.Path;

            try
            {
                page.RenderingContext = viewRenderingContext;
                await page.ExecuteAsync();

                return(writer);
            }
            finally
            {
                viewRenderingContext.Writer = oldWriter;
                //context.ExecutingFilePath = oldFilePath;
            }
        }
Exemple #4
0
        /// <inheritdoc />
        public void Activate([NotNull] IRazorPage page, [NotNull] ViewContext context)
        {
            var activationInfo = _activationInfo.GetOrAdd(page.GetType(),
                                                          CreateViewActivationInfo);

            context.ViewData = CreateViewDataDictionary(context, activationInfo);

            for (var i = 0; i < activationInfo.PropertyActivators.Length; i++)
            {
                var activateInfo = activationInfo.PropertyActivators[i];
                activateInfo.Activate(page, context);
            }
        }
    public void Activate(IRazorPage page, ViewContext context)
    {
        var view = context.View;

        this.DefaultActivator.Activate(page, context);
        if (!(page is RazorPageAdapter))
        {
            var componentHelper = (IViewComponentHelper)page.GetType().GetProperty("Component").GetValue(page);
            // Maybe we should add the page type information. to get back extactly the helper for the desired page.
            this.HttpContextAccessor.HttpContext.Items[nameof(CoreExtensions.ViewComponentHelper)] = componentHelper;
            this.HttpContextAccessor.HttpContext.Items[nameof(CoreExtensions.RazorPage)]           = page;
        }
    }
        internal RazorPagePropertyActivator GetOrAddCacheEntry(IRazorPage page)
        {
            var  pageType          = page.GetType();
            Type?providedModelType = null;

            if (page is IModelTypeProvider modelTypeProvider)
            {
                providedModelType = modelTypeProvider.GetModelType();
            }

            // We only need to vary by providedModelType since it varies at runtime. Defined model type
            // is synonymous with the pageType and consequently does not need to be accounted for in the cache key.
            var cacheKey = new CacheKey(pageType, providedModelType);

            if (!_activationInfo.TryGetValue(cacheKey, out var propertyActivator))
            {
                // Look for a property named "Model". If it is non-null, we'll assume this is
                // the equivalent of TModel Model property on RazorPage<TModel>.
                //
                // Otherwise if we don't have a model property the activator will just skip setting
                // the view data.
                var modelType = providedModelType;
                if (modelType == null)
                {
                    modelType = pageType.GetRuntimeProperty(ModelPropertyName)?.PropertyType;
                }

                propertyActivator = new RazorPagePropertyActivator(
                    pageType,
                    modelType,
                    _metadataProvider,
                    _propertyAccessors);

                propertyActivator = _activationInfo.GetOrAdd(cacheKey, propertyActivator);
            }

            return(propertyActivator);
        }
        /// <inheritdoc />
        public void Activate(IRazorPage page, ViewContext context)
        {
            if (page == null)
            {
                throw new ArgumentNullException(nameof(page));
            }

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var activationInfo = _activationInfo.GetOrAdd(page.GetType(),
                                                          CreateViewActivationInfo);

            context.ViewData = CreateViewDataDictionary(context, activationInfo);

            for (var i = 0; i < activationInfo.PropertyActivators.Length; i++)
            {
                var activateInfo = activationInfo.PropertyActivators[i];
                activateInfo.Activate(page, context);
            }
        }
        async Task RenderLayoutAsync(IViewBufferScope bufferScope, IRazorPage previousPage, ViewResult viewResult, ViewRenderingContext viewRenderingContext, ViewBufferTextWriter bodyWriter)
        {
            // A layout page can specify another layout page. We'll need to continue
            // looking for layout pages until they're no longer specified.
            var renderedLayouts = new List <IRazorPage>();

            // This loop will execute Layout pages from the inside to the outside. With each
            // iteration, bodyWriter is replaced with the aggregate of all the "body" content
            // (including the layout page we just rendered).
            while (!string.IsNullOrEmpty(previousPage.Layout))
            {
                if (!bodyWriter.IsBuffering)
                {
                    // Once a call to RazorPage.FlushAsync is made, we can no longer render Layout pages - content has
                    // already been written to the client and the layout content would be appended rather than surround
                    // the body content. Throwing this exception wouldn't return a 500 (since content has already been
                    // written), but a diagnostic component should be able to capture it.

                    var message = "Resources.FormatLayoutCannotBeRendered(Path, nameof(New.RazorPage.FlushAsync))";
                    throw new InvalidOperationException(message);
                }

                var layoutPage = this.GetLayoutPage(viewResult, previousPage.PipelineContext, previousPage.Layout);

                if (renderedLayouts.Count > 0 && renderedLayouts.Any(l => l.GetType() == layoutPage.GetType()))
                {
                    // If the layout has been previously rendered as part of this view, we're potentially in a layout
                    // rendering cycle.
                    throw new InvalidOperationException("Layout has circular reference. Previous Page: `" + previousPage.GetType() + "`, Current Layout: `" + layoutPage.GetType() + "`");
                }

                // Notify the previous page that any writes that are performed on it are part of sections being written
                // in the layout.
                previousPage.IsLayoutBeingRendered = true;
                layoutPage.PreviousSectionWriters  = previousPage.SectionWriters;
                layoutPage.BodyContent             = bodyWriter.Buffer;
                bodyWriter = await this.RenderPageAsync(bufferScope, layoutPage, viewRenderingContext);

                renderedLayouts.Add(layoutPage);
                previousPage = layoutPage;
            }

            // Now we've reached and rendered the outer-most layout page. Nothing left to execute.

            // Ensure all defined sections were rendered or RenderBody was invoked for page without defined sections.
            foreach (var layoutPage in renderedLayouts)
            {
                layoutPage.EnsureRenderedBodyOrSections();
            }

            if (bodyWriter.IsBuffering)
            {
                // If IsBuffering - then we've got a bunch of content in the view buffer. How to best deal with it
                // really depends on whether or not we're writing directly to the output or if we're writing to
                // another buffer.
                var viewBufferTextWriter = viewRenderingContext.Writer as ViewBufferTextWriter;
                if (viewBufferTextWriter == null || !viewBufferTextWriter.IsBuffering)
                {
                    // This means we're writing to a 'real' writer, probably to the actual output stream.
                    // We're using PagedBufferedTextWriter here to 'smooth' synchronous writes of IHtmlContent values.
                    using (var writer = bufferScope.CreateWriter(viewRenderingContext.Writer))
                        await bodyWriter.Buffer.WriteToAsync(writer, this.htmlEncoder);
                }
                else
                {
                    // This means we're writing to another buffer. Use MoveTo to combine them.
                    bodyWriter.Buffer.MoveTo(viewBufferTextWriter.Buffer);
                }
            }
        }