So I'm playing around with the TM .NET API v2 within some event code.
I'm interested in adjusting the Xml sent from TM for translation so am subscribing to IItemSendEventArgs
.
EventSystem.Subscribe<ITranslationJob, IItemSendEventArgs>(OnTranslationJobSent, EventPhases.Initiated, EventSubscriptionOrder.Early);
So far so good.
I know I'm sending only components for translation and I know I'll need to get at the Component itself inside this event code. From what I can see in the TM .NET API v2 you don't get the actual Component but IResolvedItem
an ITcmItem
- kind of light weight versions.
In order to get an actual Component I'm trying the following (based on info from my previous Session question:
private void OnTranslationJobSent(ITranslationJob job, IItemSendEventArgs e, EventPhases phase)
{
job.TmSession.Log(false, "OnTranslationJobSent");
try
{
var item = e.Item.IncludedItems.First();
using (var session = ((IdentifiableObject)job).Session)
{
var comp = (Component)session.GetObject(item.SourceItemUri);
}
}
catch
{
// bad
}
}
But when I run this, my translation jobs always error with the following notification:
Translation Job id: 64
Translation Job title: Example News 1...
Source Publication URI: tcm:0-14-1
Source Publication title: 200 Example Content
Source Item URI: tcm:14-567
Source Item title: Example News 1
EventSystem.DeliverEvent must be called with EventDeliveryPhase.Initiated before it is called with EventDeliveryPhase.Processed.
at Tridion.ContentManager.Extensibility.EventSystem.DeliverEvent(IEnumerable`1 subjects, TcmEventArgs eventArgs, EventDeliveryPhase deliveryPhase)
at Tridion.ContentManager.Extensibility.EventSystem.DeliverEvent(IdentifiableObject subject, TcmEventArgs eventArgs, EventDeliveryPhase deliveryPhase)
at Tridion.TranslationManager.DomainModel.EventSystem.EventSystemHelper.DeliverEvent(Object subject, TmEventArgs eventArgs, EventDeliveryPhase deliveryPhase)
at Tridion.TranslationManager.DomainModel.Service.SendForTranslationTask.ProcessClient(TranslationJob job, String clientId, List`1 resolvedItems)
at Tridion.TranslationManager.DomainModel.Service.SendForTranslationTask.Process()
at Tridion.TranslationManager.DomainModel.Service.ServiceTask.ThreadMethod()
It seems if I don't use Session, I don't get the error.
I've noted Rick's answer on another post, is this a case of, as Rick put's it:
multi-threaded use of a single TOM.NET Session
I didn't think it was, but clearly my usage is causing the error.
Can anyone advise on the correct way to access TOM.NET Session within TM event code?
UPDATE
If I create a brand new Session, the error goes away:
using (var session = new Session("domain\\Administrator"))
{
var comp = (Component)session.GetObject(item.SourceItemUri);
}
But I'd always believed this was bad practice? Especially when you can retrieve Session from an existing subject.
UPDATE
As Yuri mentions, I was incorrectly disposing the session. I've updated this but if I try and actually use the Component the error returns:
try
{
var item = e.Item.IncludedItems.First();
var session = ((IdentifiableObject)job).Session;
var comp = (Component)session.GetObject(item.SourceItemUri);
ResolveContainingPagesInstruction instruction = new ResolveContainingPagesInstruction()
{
IncludeComponentMetadataLinks = true,
IncludeDynamicVersion = true,
IncludePageMetadataLinks = true,
IncludeWorkflow = true,
ResolvePublishedPagesOnly = true
};
var pages = comp.ResolveContainingPages(instruction);
foreach (var page in pages)
{
var url = ((Page)page.Key.Item).GetPublishUrl("Staging");
if (url != null)
{
var previewUrl = item.CreatePreviewUrl(url.ToString());
previewUrl.Attributes.Add("tcm", page.Key.Item.Id);
previewUrl.Attributes.Add("title", page.Key.Item.Title);
item.PreviewUrls.Add(previewUrl);
}
}
}
catch (Exception ex)
{
// bad
}
Cheers