8

I have the following code in my controller:

string[] componentIds = new string[] {"tcm:26-123","tcm:26-456", "tcm:26-789"};
ComponentFactory cf = new ComponentFactory();
var components = cf.GetComponents(componentIds);

All 3x components use the same dynamic component template which contains standard DD4T logic.

The code executes without errors when the 3x components are published but I get the following error when I unpublish one of the components:

Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
Source Error:
Line 155:            var components =
Line 156:                componentUris
Line 157:                .Select(componentUri => { TcmUri uri = new TcmUri(componentUri); return (T.ComponentPresentation)GetComponentPresentationFactory(uri.PublicationId).FindAllComponentPresentations(componentUri)[0]; })
Line 158:                .Where(cp => cp != null)
Line 159:                .Select(cp => cp.Content)

Notice that the code FindAllComponentPresentations(componentUri)[0] is assuming a result (e.g. [0]) and that this is causing the error.

The DD4T method GetComponents has a comment 'Returns the Component contents which could be found. Components that couldn't be found don't appear in the list.' but this doesn't seem to be true because FindAllComponentPresentations errors if the component doesn't exist, rather than returning null.

Question: Is GetComponents working in the expected behaviour?

Thanks in advance

2 Answers 2

8

This is indeed expected, albeit not very elegant behaviour. The GetComponents method is primary intended to retrieve components from a list of URIs which was returned by a broker query. In that case, the chance that one of those components does not actually exist is slim.

Personally, I don't use the 'batch' method GetComponents much, I usually use the GetComponent method for each URI, allowing me to handle exceptions as I see fit. There is no performance penalty if you get the components one by one either, since 'under water' each URI triggers a call to GetComponent anyway.

I'm open to suggestions on how we could improve the GetComponents method by the way.

1
  • 1
    Thanks very much Quirijn, it's great to know that using the GetComponent method incurs no performance penalty. GetContentMultiple may work returning null if no components found? I'll give an example in a separate answer. Commented Jul 2, 2013 at 13:05
4

Thanks for your answer Quirijn. Potentially GetContentMultiple could work as follows:

public List<string> GetContentMultiple(string[] componentUris)
{
    var components =
        componentUris
        .Select(componentUri => 
        {  
            TcmUri uri = new TcmUri(componentUri); 
            IList cpList = GetComponentPresentationFactory(uri.PublicationId).FindAllComponentPresentations(componentUri);
            if (cpList.Count > 0)
            {
                return (T.ComponentPresentation)cpList[0];
            }
            return null;
        })
        .Where(cp => cp != null)
        .Select(cp => cp.Content)
        .ToList();
    return components;
}
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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