public async Task BuildDisplayAsync()

in src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentItemDisplayCoordinator.cs [63:217]


        public async Task BuildDisplayAsync(ContentItem contentItem, BuildDisplayContext context)
        {
            var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(contentItem.ContentType);

            if (contentTypeDefinition == null)
            {
                return;
            }

            foreach (var displayDriver in _displayDrivers)
            {
                try
                {
                    var result = await displayDriver.BuildDisplayAsync(contentItem, context);
                    if (result != null)
                    {
                        await result.ApplyAsync(context);
                    }
                }
                catch (Exception ex)
                {
                    InvokeExtensions.HandleException(ex, _logger, displayDriver.GetType().Name, nameof(BuildDisplayAsync));
                }
            }

            foreach (var contentTypePartDefinition in contentTypeDefinition.Parts)
            {
                var partName = contentTypePartDefinition.Name;
                var partTypeName = contentTypePartDefinition.PartDefinition.Name;
                var contentType = contentTypePartDefinition.ContentTypeDefinition.Name;
                var partActivator = _contentPartFactory.GetTypeActivator(partTypeName);
                var part = contentItem.Get(partActivator.Type, partName) as ContentPart;

                if (part != null)
                {
                    var partDisplayDrivers = _contentPartDisplayDriverResolver.GetDisplayModeDrivers(partTypeName, contentTypePartDefinition.DisplayMode());
                    foreach (var partDisplayDriver in partDisplayDrivers)
                    {
                        try
                        {
                            var result = await partDisplayDriver.BuildDisplayAsync(part, contentTypePartDefinition, context);
                            if (result != null)
                            {
                                await result.ApplyAsync(context);
                            }
                        }
                        catch (Exception ex)
                        {
                            InvokeExtensions.HandleException(ex, _logger, partDisplayDrivers.GetType().Name, nameof(BuildDisplayAsync));
                        }
                    }
                    // TODO: This can be removed in a future release as the recommended way is to use ContentOptions.
                    // Iterate existing driver registrations as multiple drivers maybe not be registered with ContentOptions.
                    foreach (var displayDriver in _partDisplayDrivers)
                    {
                        try
                        {
                            var result = await displayDriver.BuildDisplayAsync(part, contentTypePartDefinition, context);
                            if (result != null)
                            {
                                await result.ApplyAsync(context);
                            }
                        }
                        catch (Exception ex)
                        {
                            InvokeExtensions.HandleException(ex, _logger, displayDriver.GetType().Name, nameof(BuildDisplayAsync));
                        }
                    }
                    var tempContext = context;

                    // Create a custom ContentPart shape that will hold the fields for dynamic content part (not implicit parts)
                    // This allows its fields to be grouped and templated

                    if (part.GetType() == typeof(ContentPart) && partTypeName != contentTypePartDefinition.ContentTypeDefinition.Name)
                    {
                        var shapeType = context.DisplayType != "Detail" ? "ContentPart_" + context.DisplayType : "ContentPart";

                        var shapeResult = new ShapeResult(shapeType, ctx => ctx.ShapeFactory.CreateAsync(shapeType, () => new ValueTask<IShape>(new ZoneHolding(() => ctx.ShapeFactory.CreateAsync("Zone")))));
                        shapeResult.Differentiator(partName);
                        shapeResult.Location("Content");

                        await shapeResult.ApplyAsync(context);

                        var contentPartShape = shapeResult.Shape;

                        // Make the ContentPart name property available on the shape
                        dynamic dynamicContentPartShape = contentPartShape;
                        dynamicContentPartShape[partTypeName] = part.Content;
                        dynamicContentPartShape["ContentItem"] = part.ContentItem;

                        contentPartShape.Metadata.Alternates.Add(partTypeName);
                        contentPartShape.Metadata.Alternates.Add($"{contentType}__{partTypeName}");

                        if (context.DisplayType != "Detail")
                        {
                            contentPartShape.Metadata.Alternates.Add($"{partTypeName}_{context.DisplayType}");
                            contentPartShape.Metadata.Alternates.Add($"{contentType}_{context.DisplayType}__{partTypeName}");
                        }

                        if (partName != partTypeName)
                        {
                            contentPartShape.Metadata.Alternates.Add($"{contentType}__{partName}");

                            if (context.DisplayType != "Detail")
                            {
                                contentPartShape.Metadata.Alternates.Add($"{contentType}_{context.DisplayType}__{partName}");
                            }
                        }

                        context = new BuildDisplayContext(shapeResult.Shape, context.DisplayType, context.GroupId, context.ShapeFactory, context.Layout, context.Updater);
                        // With a new display context we have the default FindPlacementDelegate that returns null, so we reuse the delegate from the temp context.
                        context.FindPlacement = tempContext.FindPlacement;
                    }

                    foreach (var contentPartFieldDefinition in contentTypePartDefinition.PartDefinition.Fields)
                    {
                        var fieldDisplayDrivers = _contentFieldDisplayDriverResolver.GetDisplayModeDrivers(contentPartFieldDefinition.FieldDefinition.Name, contentPartFieldDefinition.DisplayMode());
                        foreach (var fieldDisplayDriver in fieldDisplayDrivers)
                        {
                            try
                            {
                                var result = await fieldDisplayDriver.BuildDisplayAsync(part, contentPartFieldDefinition, contentTypePartDefinition, context);
                                if (result != null)
                                {
                                    await result.ApplyAsync(context);
                                }
                            }
                            catch (Exception ex)
                            {
                                InvokeExtensions.HandleException(ex, _logger, fieldDisplayDriver.GetType().Name, nameof(BuildDisplayAsync));
                            }
                        }
                        // TODO: This can be removed in a future release as the recommended way is to use ContentOptions.
                        // Iterate existing driver registrations as multiple drivers maybe not be registered with ContentOptions.
                        foreach (var displayDriver in _fieldDisplayDrivers)
                        {
                            try
                            {
                                var result = await displayDriver.BuildDisplayAsync(part, contentPartFieldDefinition, contentTypePartDefinition, context);
                                if (result != null)
                                {
                                    await result.ApplyAsync(context);
                                }
                            }
                            catch (Exception ex)
                            {
                                InvokeExtensions.HandleException(ex, _logger, displayDriver.GetType().Name, nameof(BuildDisplayAsync));
                            }
                        }
                    }

                    context = tempContext;
                }
            }
        }