4

Restrict publishing of Linked component withinn Parent Component using C# Template

We have a dynamic component template and I want to restrict the Publishing of Linked-Component which is within Parent component based on Linked component schema. I am able to stop publishing the Parent component, but Linked component within parent component is getting published.

When I am trying to get the rendered Item, I am getting only the parent component.

Please find below my code.

Component _component = (Component)engine.GetObject("tcm:125-234567");
ComponentTemplate templateToBePublished = (ComponentTemplate)engine.GetObject("tcm:275-120870-32");
RenderInstruction renderInstruction = engine.PublishingContext.RenderedItem.RenderInstruction;
RenderedItem itemToRender = new RenderedItem(new ResolvedItem(_component, templateToBePublished), renderInstruction);

ResolveInstruction resolveInstruction = engine.PublishingContext.PublishInstruction.ResolveInstruction;

PublicationTarget target;

if (engine.RenderMode == RenderMode.Publish)
{
    target = engine.PublishingContext.PublicationTarget;                
}
else
{
    target = (PublicationTarget)engine.GetObject("tcm:0-48-65537");                
}


PublishContext pubContext = new PublishContext((Publication)_component.ContextRepository, target);

Set<ResolvedItem> resolvedItems = new Set<ResolvedItem>();
resolvedItems = (Set<ResolvedItem>)ResolveEngine.ResolveItem(_component, resolveInstruction, pubContext);

Logger.Debug($"ComponentList - resolvedItem:  '{resolvedItems.Count}'");
foreach (ResolvedItem resolvedItem in resolvedItems)
{
    
    IdentifiableObject item = resolvedItem.Item;
    if (item.Id.ItemType == ItemType.Component)
    {
        // based on the schema type I will be stop publishing.
        if (item.Schema.Title == "Core Schema - Component List")
            {
                bool stopPublishing = StopPublish(engine, package, transformContext, repository);
                if (stopPublishing)
                {
                    throw new Exception($"CoreSchemaTemplate: Component items field without Core Scema - Link component is not allowed to publish. Exit publishing.");

                }
            }
    }
}

Created Custom Resolver, the Resolve method is called twice and everytime the resolveItems.Count is 1, based on my logic I try to remove the resolved Item, but this is not working. any solution to this would be a great help.

public void Resolve(IdentifiableObject item, ResolveInstruction instruction, PublishContext context, Tridion.Collections.ISet<ResolvedItem> resolvedItems)
        {
            var capiTargetPartName = "CAPI v2";
            var capiComponentTemplateName = "CAPI.v2";
            log.Info("::resolvedItems.Count = " + resolvedItems.Count, LoggerCategory.Publishing);
            if (item is Component && context.PublicationTarget.Title.Contains(capiTargetPartName) && (instruction.Purpose == ResolvePurpose.Publish || instruction.Purpose == ResolvePurpose.RePublish))
            {
                try
                {
                    Component rootComponent = (Component)item;
                    log.Info("rootComponent.Title = " + rootComponent.Title, LoggerCategory.Publishing);
                    if (rootComponent.Schema.Title == "Core Schema - Component List")
                    {
                        // find capi target
                        PublicationTarget capiTarget = resolvedItems.Select(x => x.PublicationTarget).FirstOrDefault(x => x.Title.Contains(capiTargetPartName));
                        if (capiTarget == null)
                            return;

                        // find capi component template
                        ComponentTemplate capiComponentTemplate = resolvedItems.Select(x => x.Template).FirstOrDefault(x => x.Title.Contains(capiComponentTemplateName)) as ComponentTemplate;
                        if (capiComponentTemplate == null)
                            return;

                        // find components resolved by default resolver
                        List<Component> components = resolvedItems.Where(x => x.Template.Id == capiComponentTemplate.Id).Select(x => x.Item).Cast<Component>().ToList();
                        if (!components.Any())
                            return;

                        //allowed schemas
                        List<int> allowedSchemas = capiComponentTemplate.RelatedSchemas.Select(x => x.Id.ItemId).Distinct().ToList();

                        //linked components
                        List<int> usedComponents = GetUsedComponentsRecursive(rootComponent, allowedSchemas).Select(x => x.Id.ItemId).ToList();

                        foreach (Component component in components)
                        {
                            log.Info("Resolved component.Title = " + component.Title, LoggerCategory.Publishing);
                            //resolve linked components
                            foreach (int usedComponentId in usedComponents)
                            {
                                //id of used component in child publication
                                TcmUri bpUsedComponentId = new TcmUri(usedComponentId, ItemType.Component, context.Publication.Id.ItemId);
                                Component usedComponent = component.Session.GetObject(bpUsedComponentId) as Component;
                                //usedComponent.Load(LoadFlags.None);

                                ResolvedItem resolvedItem = new ResolvedItem(usedComponent, capiComponentTemplate, capiTarget);
                                resolvedItems.Remove(resolvedItem);                               
                            }
                        }

                    }
                    
                }
                catch (Exception ex)
                {
                    log.Info("CapiComponentResolver execution failed: " + ex, LoggerCategory.Publishing);
                }
5
  • Sunil can you share the Tridion Version you are using
    – Anand N S
    Oct 27, 2021 at 8:21
  • Hi Anand, we have "Tridion Sites Content Manager - Build 9.1.0" Oct 27, 2021 at 8:52
  • are you doing this in custom resolver? Oct 27, 2021 at 9:08
  • Hi Marko, I am doing this in custom templating. Oct 28, 2021 at 6:09
  • 1
    Hi Sunil, welcome to Tridion Stack Exchange. For background, Templating adds or removes items to the package, which might include Images or component Presentations. I wouldn't expect "resolving" logic in custom templating code. By default linked Components are not automatically published. See my post on the default resolving logic. So either custom resolving (perhaps DXA) or templating code might be adding these linked Components to the package.
    – Alvin Reyes
    Nov 2, 2021 at 14:22

1 Answer 1

2

OK, so here is the catch. You are working with dynamic components. Just like your main component is rendered separately from the page it is in, the same applies to your linked components. Your linked components are rendered separately, in their own render context. In your main component, at the end of rendering, you will just have a reference to it (your tcdl tag).

So how and where do you influence this?

My suggestion would be a custom resolver. In custom resolver, you have access to all resolved items within transaction. So I would suggest trying that. Resolving happens before rendering, so you will do it even faster, so that you have less processing time on the publishing system.

Also, as a word of advice, if you have to break publishing so that the linked component is not published, it normally points to bad content design. Why do you have these kinds of components linked in the first place? Maybe in the future, you can give a look at your content schemas and templates and try to give some design overhaul to the system.

2
  • 3
    By default, Tridion Sites will not published linked Components. :-) The default resolving logic will publish dynamic Component Presentations (DCPs) referenced from a page (and only those DCPs explicitly chosen) or all the DCPs from "dynamic" templates associated with the Schema of a queued Component. See my post on the resolving logic. DXA and customer code might add more DCPS, but that's more on code rather than the content model, per se. ;-)
    – Alvin Reyes
    Nov 2, 2021 at 14:27
  • Hi, I have created Custom Resolver, but when I am getting the resolvedItems.Count =1 Nov 8, 2021 at 7:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.