public async Task <IHtmlContent> RenderComponentAsync(
            ViewContext viewContext,
            Type componentType,
            RenderMode renderMode,
            object parameters)
        {
            if (viewContext is null)
            {
                throw new ArgumentNullException(nameof(viewContext));
            }

            if (componentType is null)
            {
                throw new ArgumentNullException(nameof(componentType));
            }

            if (!typeof(IComponent).IsAssignableFrom(componentType))
            {
                throw new ArgumentException(Resources.FormatTypeMustDeriveFromType(componentType, typeof(IComponent)));
            }

            var context       = viewContext.HttpContext;
            var parameterView = parameters is null ?
                                ParameterView.Empty :
                                ParameterView.FromDictionary(HtmlHelper.ObjectToDictionary(parameters));

            return(renderMode switch
            {
                RenderMode.Server => NonPrerenderedServerComponent(context, GetOrCreateInvocationId(viewContext), componentType, parameterView),
                RenderMode.ServerPrerendered => await PrerenderedServerComponentAsync(context, GetOrCreateInvocationId(viewContext), componentType, parameterView),
                RenderMode.Static => await StaticComponentAsync(context, componentType, parameterView),
                RenderMode.WebAssembly => NonPrerenderedWebAssemblyComponent(context, componentType, parameterView),
                RenderMode.WebAssemblyPrerendered => await PrerenderedWebAssemblyComponentAsync(context, componentType, parameterView),
                _ => throw new ArgumentException(Resources.FormatUnsupportedRenderMode(renderMode), nameof(renderMode)),
            });
        /// <summary>
        /// Renders the <typeparamref name="TComponent"/> <see cref="IComponent"/>.
        /// </summary>
        /// <param name="htmlHelper">The <see cref="IHtmlHelper"/>.</param>
        /// <param name="parameters">An <see cref="object"/> containing the parameters to pass
        /// to the component.</param>
        /// <returns>The HTML produced by the rendered <typeparamref name="TComponent"/>.</returns>
        public static async Task <IHtmlContent> RenderComponentAsync <TComponent>(
            this IHtmlHelper htmlHelper,
            object parameters) where TComponent : IComponent
        {
            if (htmlHelper == null)
            {
                throw new System.ArgumentNullException(nameof(htmlHelper));
            }

            var serviceProvider = htmlHelper.ViewContext.HttpContext.RequestServices;
            var encoder         = serviceProvider.GetRequiredService <HtmlEncoder>();

            using (var htmlRenderer = new HtmlRenderer(serviceProvider, encoder.Encode))
            {
                var result = await htmlRenderer.RenderComponentAsync <TComponent>(
                    parameters == null?
                    ParameterCollection.Empty :
                    ParameterCollection.FromDictionary(HtmlHelper.ObjectToDictionary(parameters)));

                return(new ComponentHtmlContent(result));
            }
        }
        /// <summary>
        /// Renders the <typeparamref name="TComponent"/> <see cref="IComponent"/>.
        /// </summary>
        /// <param name="htmlHelper">The <see cref="IHtmlHelper"/>.</param>
        /// <param name="parameters">An <see cref="object"/> containing the parameters to pass
        /// to the component.</param>
        /// <returns>The HTML produced by the rendered <typeparamref name="TComponent"/>.</returns>
        public static async Task <IHtmlContent> RenderStaticComponentAsync <TComponent>(
            this IHtmlHelper htmlHelper,
            object parameters) where TComponent : IComponent
        {
            if (htmlHelper == null)
            {
                throw new ArgumentNullException(nameof(htmlHelper));
            }

            var httpContext     = htmlHelper.ViewContext.HttpContext;
            var serviceProvider = httpContext.RequestServices;
            var prerenderer     = serviceProvider.GetRequiredService <StaticComponentRenderer>();

            var parametersCollection = parameters == null ?
                                       ParameterCollection.Empty :
                                       ParameterCollection.FromDictionary(HtmlHelper.ObjectToDictionary(parameters));

            var result = await prerenderer.PrerenderComponentAsync(
                parametersCollection,
                httpContext,
                typeof(TComponent));

            return(new ComponentHtmlContent(result));
        }
Exemple #4
0
        public IHtmlContent Build()
        {
            if (_metadata.ConvertEmptyStringToNull && string.Empty.Equals(_model))
            {
                _model = null;
            }

            // Normally this shouldn't happen, unless someone writes their own custom Object templates which
            // don't check to make sure that the object hasn't already been displayed
            if (_viewData.TemplateInfo.Visited(_modelExplorer))
            {
                return(HtmlString.Empty);
            }

            // Create VDD of type object so any model type is allowed.
            var viewData = new ViewDataDictionary <object>(_viewData);

            // Create a new ModelExplorer in order to preserve the model metadata of the original _viewData even
            // though _model may have been reset to null. Otherwise we might lose track of the model type /property.
            viewData.ModelExplorer = _modelExplorer.GetExplorerForModel(_model);

            var formatString = _readOnly ?
                               viewData.ModelMetadata.DisplayFormatString :
                               viewData.ModelMetadata.EditFormatString;

            var formattedModelValue = _model;

            if (_model == null)
            {
                if (_readOnly)
                {
                    formattedModelValue = _metadata.NullDisplayText;
                }
            }
            else if (!string.IsNullOrEmpty(formatString))
            {
                formattedModelValue = string.Format(CultureInfo.CurrentCulture, formatString, _model);
            }
            else if ((string.Equals("week", _templateName, StringComparison.OrdinalIgnoreCase) ||
                      string.Equals("week", viewData.ModelMetadata.DataTypeName, StringComparison.OrdinalIgnoreCase)))
            {
                // "week" is a new HTML5 input type that only will be rendered in Rfc3339 mode
                formattedModelValue = FormatWeekHelper.GetFormattedWeek(_modelExplorer);
            }
            else if (viewData.ModelMetadata.IsEnum && _model is Enum modelEnum)
            {
                // Cover the case where the model is an enum and we want the string value of it
                var value       = modelEnum.ToString("d");
                var enumGrouped = viewData.ModelMetadata.EnumGroupedDisplayNamesAndValues;
                Debug.Assert(enumGrouped != null);
                foreach (var kvp in enumGrouped)
                {
                    if (kvp.Value == value)
                    {
                        // Creates a ModelExplorer with the same Metadata except that the Model is a string instead of an Enum
                        formattedModelValue = kvp.Key.Name;
                        break;
                    }
                }
            }

            viewData.TemplateInfo.FormattedModelValue = formattedModelValue;
            viewData.TemplateInfo.HtmlFieldPrefix     = _viewData.TemplateInfo.GetFullHtmlFieldName(_htmlFieldName);

            if (_additionalViewData != null)
            {
                foreach (var kvp in HtmlHelper.ObjectToDictionary(_additionalViewData))
                {
                    viewData[kvp.Key] = kvp.Value;
                }
            }

            var visitedObjectsKey = _model ?? _modelExplorer.ModelType;

            viewData.TemplateInfo.AddVisited(visitedObjectsKey);

            var templateRenderer = new TemplateRenderer(
                _viewEngine,
                _bufferScope,
                _viewContext,
                viewData,
                _templateName,
                _readOnly);

            return(templateRenderer.Render());
        }