0

we're using a custom Amazon S3 ECL Provider. The problem is that there are some Components that have titles longer than 255 character long and it's throwing an exception. The problem is that the file system doesn't support more than 255 characters on the name of the file (Windows 2012).

As a solution I'm trying to convert those titles into something smaller so the filename will be less that 255. I can encode using MD5 the eclUri to a number calling the ECL Service method CreateOrGetStubUris and it works. Then I have two problems:

  1. Where do I store the original name of the file (probably I can save it in the metadata of the stub.
  2. If I don't create the stub manually calling CreateOrGetStubUris and the stub gets created automatically (hitting the method StubComponentCreated in the provider) how do I change its title? In that method I can't access the stub as I'm still inside the transaction and the stub doesn't exist yet, right? I need to store the original file name since MD5 is one way and I can't get the original filename from the MD5.

UPDATE

The problem is when selecting a Mountpoint item which has a very long name while saving a component. This is the stacktrace of the exception thrown while saving the component.

Invalid value for property 'Title'. The length of the Title property must be between 1 and 255 characters.
   at Tridion.ContentManager.IdentifiableObject.ValidateSystemConstraints()
   at Tridion.ContentManager.IdentifiableObject.ValidatePropertyConstraints()
   at Tridion.ContentManager.IdentifiableObject.OnSaving(SaveEventArgs eventArgs)
   at Tridion.ContentManager.ContentManagement.RepositoryLocalObject.OnSaving(SaveEventArgs eventArgs)
   at Tridion.ContentManager.ContentManagement.VersionedItem.OnSaving(SaveEventArgs eventArgs)
   at Tridion.ContentManager.ContentManagement.Component.OnSaving(SaveEventArgs eventArgs)
   at Tridion.ContentManager.IdentifiableObject.Save(SaveEventArgs eventArgs)
   at Tridion.ContentManager.ContentManagement.VersionedItem.Save(Boolean checkInAfterSave)
   at Tridion.ExternalContentLibrary.DomainModel.StubItem.CreateNewStubItem(TcmUri stubFolderUri, IEclUri eclUri, MountPoint mountPoint, Boolean checkInAfterSave, XmlElement metadata)
   at Tridion.ExternalContentLibrary.DomainModel.StubItem.<>c__DisplayClass1.<CreateOrGetStubId>b__0(TcmUri parentFolderUri)
   at Tridion.ExternalContentLibrary.DomainModel.TcmObjectCreator.GetOrCreateItemUri(Session session, TcmUri parentItemUri, String itemName, Func`2 create)
   at Tridion.ExternalContentLibrary.DomainModel.TcmObjectCreator.<>c__DisplayClass4.<GetOrCreateItemUri>b__2()
   at Tridion.Infrastructure.Caching.Cache`3.GetOrCreateWithBatchRead(TKey key, TValidatorState validateState, Func`1 createNewValues)
   at Tridion.ExternalContentLibrary.DomainModel.TcmObjectCreator.GetOrCreateItemUri(TcmUri parentItemUri, IEnumerable`1 path, UserContext userContext, Func`2 create)
   at Tridion.ExternalContentLibrary.DomainModel.StubItem.CreateOrGetStubId(IEclUri eclItemUri, MountPoint mountPoint, Boolean checkInAfterSave, XmlElement metadata)
   at Tridion.ExternalContentLibrary.DomainModel.UserContext.ExecutePrivileged[T](String userName, Func`1 privilegedCode)
   at Tridion.ExternalContentLibrary.DomainModel.MountPoint.<CreateOrGetStubUris>b__5f(<>f__AnonymousType3`2 <>h__TransparentIdentifier59)
   at System.Linq.Enumerable.<>c__DisplayClass7_0`3.<CombineSelectors>b__0(TSource x)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector)
   at SyncInvokeCreateOrGetStubUris(Object , Object[] , Object[] )
   at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
2

The problem is in the provider, so your solution is also in there. DO NOT try to change the stub after it has been created, a stub Component for ECL is supposed to be a hidden item that is there for internal purposes only, and when you try to manipulate it, you will create issues in ECL (there is an event handler which will already prevent you from making certain changes to it, but in essense you NEVER need to touch the stub Component directly).

Your only solution is to modify the Amazon S3 ECL Provider to use a shorter string for the ECL URI and you can add the original filename as metadata of the ECL item (that is how it should have been developed in the first place). See for example how I did that in the Flickr ECL provider I created as an example a long time ago: https://github.com/bkoopman/sdl-tridion-world/blob/master/Flickr%20ECL%20Provider/trunk/Flickr%20ECL%20Provider/FlickrPhoto.cs#L134

Please note that using a MD5 hash as your item ID might also cause you problems eventually, since a hash is not per definition unique (hashes are not about "unique", they are about "unique enough").

  • Thanks for you quick answer. I've being reviewing Flickr code and I understand you use as eclid something like [flickr photo id]_[flickr photo secret]_[flickr photo set id], but with Amazon S3 the id is the Key (the full name of the file, so I don't have a small number to replace it with.I think the problem is the long name of the zip file in the ThumbnailCache folder and to change that I don't understand how can I accomplish it without using an algorithm that shortens the name. Please let me know if I'm missing something. – polonskyg Nov 8 '17 at 13:50
  • One more question, If the stub is not manually created using CreateOrGetStubUris, Who/Where/When it gets automatically created (and the called StubComponentCreated) in the Provider? – polonskyg Nov 8 '17 at 14:03
  • @polonskyg indeed the challenge for an S3 provioder is the fact that Amazon does not have a proper unique ID (with a fixed acceptable length), which is something I think you need to solve externally by means of a mapping table. Its simply a story that the available API is not sufficient for a decent ECL connection. About "who" creates the stub, once an ECL item is used (i.e. added on a Page or linked in a Component), a stub Component is created by the ECL core. That basically itself calls CreateOrGetStubUris at that time. – Bart Koopman Nov 8 '17 at 15:19
  • FYI, I've added the stacktrace. The exception is thrown when saving a component that uses the image from the mountpoint. – polonskyg Nov 8 '17 at 15:43
  • I agree with the mapping, the question is where to store that mapping to not generate a delay, Ideally not using a database or file...but a property somewhere, just don't know where. – polonskyg Nov 8 '17 at 16:07

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.