| File: TemplateBuilder.cs | Web Access |
| Project: src\aspnetcore\src\Mvc\Mvc.ViewFeatures\src\Microsoft.AspNetCore.Mvc.ViewFeatures.csproj (Microsoft.AspNetCore.Mvc.ViewFeatures) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Globalization; using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.AspNetCore.Mvc.ViewFeatures.Buffers; namespace Microsoft.AspNetCore.Mvc.ViewFeatures; internal sealed class TemplateBuilder { private readonly IViewEngine _viewEngine; private readonly IViewBufferScope _bufferScope; private readonly ViewContext _viewContext; private readonly ViewDataDictionary _viewData; private readonly ModelExplorer _modelExplorer; private object _model; private readonly ModelMetadata _metadata; private readonly string _htmlFieldName; private readonly string _templateName; private readonly bool _readOnly; private readonly object _additionalViewData; public TemplateBuilder( IViewEngine viewEngine, IViewBufferScope bufferScope, ViewContext viewContext, ViewDataDictionary viewData, ModelExplorer modelExplorer, string htmlFieldName, string templateName, bool readOnly, object additionalViewData) { ArgumentNullException.ThrowIfNull(viewEngine); ArgumentNullException.ThrowIfNull(bufferScope); ArgumentNullException.ThrowIfNull(viewContext); ArgumentNullException.ThrowIfNull(viewData); ArgumentNullException.ThrowIfNull(modelExplorer); _viewEngine = viewEngine; _bufferScope = bufferScope; _viewContext = viewContext; _viewData = viewData; _modelExplorer = modelExplorer; _htmlFieldName = htmlFieldName; _templateName = templateName; _readOnly = readOnly; _additionalViewData = additionalViewData; _model = modelExplorer.Model; _metadata = modelExplorer.Metadata; } 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(); } }