Tridion 2011 Sp1 allow to publish revision version of the component to staging target - tridion

Here is a scenario: I have a Page which have Component A. Component A have few linked components B and C. If Editor modifies component B and want to publish to staging target while component still in the workflow so Reviewer can view the changes on staging server before approve component B. When editor preview component he can see the changes, but when he publish to staging target it will grab the last checked in version of the Component A, which still linked to the unmodified version of Component B. How to pragmatically overwrite the default behavior to allow Editor publish his changes to staging environment before completing activity for the item?
Also, when component B inserted directly on the second page I was able to publish from VBScript from workflow automated activity using the following:
Dim strItemURI
strItemURI = CurrentWorkItem.GetItem(2).ID
Dim oComp
Set oComp = TDSE.GetObject(strItemURI, 1)
Call oComp.Publish("tcm:0-13-65537", True, True, False)
Set oComp = Nothing
FinishActivity "Automatic Activity ""Publish to Staging"" Finished"
Do I need to write custom resolver to accomplish above scenario to allow modified version of linked components published to staging environment while in workflow?
Any idea or samples will be appreciated.
Thanks.
Updated:
I'm trying to create TBB, which will replace modified version of the item in the package. Any idea on this? Here is some code:
public void Transform(Engine engine, Package package)
{
try
{
_publicationID = engine.PublishingContext.ResolvedItem.Item.Id.PublicationId;
string stagingTarget = Settings.GetSetting("StagingTargetUri");
PublicationTarget target = new PublicationTarget(new TcmUri(stagingTarget), engine.GetSession());
if(engine.PublishingContext.ResolvedItem.PublicationTarget!=null){
if (stagingTarget.Contains(engine.PublishingContext.ResolvedItem.PublicationTarget.Id.ToString()))
{
foreach (Item item in package.GetAllByType(ContentType.Component))
{
VersionedItem versionedItem = (VersionedItem)engine.GetObject(item);
if (versionedItem.LockType.HasFlag(LockType.InWorkflow))
{
Component componentInWorkflow =
(Component)engine.GetObject(new TcmUri(versionedItem.Id.ItemId, versionedItem.Id.ItemType, versionedItem.Id.PublicationId, 0));
package.Remove(item);
Item mainComponent= package.CreateTridionItem(ContentType.Component,componentInWorkflow);
package.PushItem(mainComponent);
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}

According to documentation:
You can publish an item in Workflow if it meets the minimum approval
status set for the Publishing Target. If the item is in Workflow and
does not meet the minimum approval status, the Content Manager
publishes the last checked-in version of the item.
This means that you need to:
Set the Minimum Approval Status on your Publication target as something like "Staging"
As a first step on your Workflow set the Approval Status for your component to "Staging"

Related

Dte.LaunchWizard not showing New Item dialog

I am trying to add a new item from an item template from a Visual Studio command. I cannot get Visual Studio to show the New Item dialog. This is in Visual Studio 2022.
Regardless of whether I use ItemOperations.AddNewItem or EnvDTE.LaunchWizard(Constants.vsWizardAddItem, ref parameters), the item is added correctly - but silently - with the default name.
This is my code to add the item using LaunchWizard (item is ProjectItem of the currently selected physical folder):
var template = ((Solution2)dte.Solution).GetProjectItemTemplate(templateName, "CSharp");
var prms = new object[]
{
Constants.vsWizardAddItem,
item.Name,
item.ProjectItems,
item.Properties.Item("FullPath").Value?.ToString(),
"Bag",
string.Empty,
false
};
var cached = dte.SuppressUI;
dte.SuppressUI = false;
try
{
dte.LaunchWizard(template, ref prms);
}
finally
{
dte.SuppressUI = cached;
}
The last value of false in the parameter array should mean that the New Item dialog is displayed. But this does not happen, the item is added silently with the default name ("Bag"). I thought maybe the EnvDTE.SuppressUI property could be the reason but setting this to false changes nothing.
We can see from this link:
The first parameter is a GUID that uniquely identifies the launch
context as distinct from Add Item or Add Project or a custom GUID.
Maybe this page can give you some help about ContextParams.
From the documentation we can see that it doesn't apply to VS 2022 SDK. Maybe you can try it in VS 2019.

Batch Export Forms from AX 2009

I'm currently working on a system that will export all the nodes from my AX 2009 AOT to individual XPO files, for the purpose of tracking changes in a central version control repository. I'm having a fair amount of luck, but for some reason I cannot get the Forms or Data Sets node to export at all.
This is my current code set:
private void export(str parentNode)
{
TreeNode node, parent;
str folderName;
Set permissions = new Set(Types::Class);
;
folderName = exportBaseDir + parentNode;
permissions.add(new FileIoPermission(folderName, "r"));
permissions.add(new InteropPermission(InteropKind::ClrInterop));
CodeAccessPermission::assertMultiple(permissions);
//Create Filesystem Folder if needed
if (!WinApiServer::pathExists(folderName))
System.IO.Directory::CreateDirectory(folderName);
CodeAccessPermission::revertAssert();
parent = TreeNode::findNode(parentNode);
if (parent)
node = parent.AOTfirstChild();
else
warning(strfmt("Could not parse node: %1", parentNode));
while (node)
{
this.exportNode(node);
node = node.AOTnextSibling();
}
}
When I call export(#"\Forms"); or export(#"\Data Sets"); I get a "Could not parse node" message, meaning the TreeNode::findNode() didn't resolve correctly. Running it on any other node (such as Classes) does not have this issue. This also only happens when it is run in a Batch -- running it with the client (with the CodeAccessPermission parts removed) will export all nodes as expected.
Is there something that would prohibit Forms and Data Sets from being accessed from within a Batch? If so, what can I do to access those nodes?
As far as I can tell it's a server/client issue/bug. The easy solution would be to create this method on your class:
client static TreeNode clientTreeNode(str _path)
{
return TreeNode::findNode(_path);
}
Then in your code, below the parent = TreeNode::findNode(parentNode); line, put:
parent = parent ? parent : YourClassHere::clientTreeNode(parentNode);
And that should solve your issue. You'll have a bit of digging to do in order to find out why it doesn't work on the server tier if you just must know.

Get shared pages using localized component

I'm currently working on a event handler, which will on save-event, save the latest revision date of the page and it's components into a custom database, and this is working, but i'm facing some performance issues.
Let me give you an example, for how it's working:
If a component is saved/updated (changes are made), then I want to update all pages using this component in my custom database.
Basic blueprint setup:
200 contains components
400 translation publication for components (inherent components from 200)
500 master publication for pages
600 local site publication inherent components from 400 and pages from 500)
So lets say we have component X in 200, this component is included in in a page in 500, X is localized in 400 (let us call it X(l)) and the page in 600 is NOT localized ( i.e it will use the component x(l))
So now to my question:
In my save event handler, i check what pages X(l) are included in , by using :
var filter = new UsingItemsFilter(component.Session)
{
IncludeLocalCopies = true,
ItemTypes = new[] { ItemType.Page }
};
but this will only give me references to pages from 500.
So what i then do (which feels kind of stupid) is to
create a tcm id of all pages in child publications(by looping over them) that inherent this page (now im using some psuedocodelike coding):
foreach(var 500page in foundPages)
foreach(var publication in publications){
if(subject.Session.IsExistingObject(
new TcmUri(page.Id.ItemId,page.Id.ItemType,publication.Id.ItemId)
))
{
someListThatWillContainAllChildPagesFrom500.Add(TheAboveTcmUri);
}
}
And then for each page, check the components in that page, and finally save this state to my custom database.
So the question is, is there a way by to query for all pages, that make use of the localized component, by using the TOM.NET api (no not CoreServiceClient)?
Is there a better way to find child publications of a publication, so I only need to check for pages in the childPublication?
Br Martin
The following code sample should give you the shared items of a specific local/localized item along with the item. BluePrintNodesFilter was introduced in 2013, however in earlier version BluePrintFilter should work in similar way.
SystemManager systemManager = session.SystemManager;
BluePrintNodesFilter filter = new BluePrintNodesFilter(session)
{
BaseColumns = ListBaseColumns.Id,
ForItem = page
};
IEnumerable<BluePrintNode> allNodes = systemManager.GetBluePrintNodes(filter);
IEnumerable<RepositoryLocalObject> sharedAndLocal = (from node in allNodes
where node.Item != null
where node.Item.OwningRepository.Id == page.OwningRepository.Id
select node.Item).ToArray();

Publishing failing in final stage of workflow

Our final automatic activity is publishing component to live target. We have below code written in Edit script.
' Script for Automatic Activity Content Manager Workflow
Set oTDSE = CreateObject("TDS.TDSE")
Call oTDSE.Initialize
Set oWorkItem = CurrentWorkItem.GetItem(3)
sDestinationServer = "tcm:0-18-65538"
Set oComp = oTDSE.GetObject(oWorkItem.ID, 3)
Call oComp.Publish(sDestinationServer, True, True, True)
FinishActivity "Automatic Activity ""Process Complete"" Finished"
set oWorkItem = Nothing
set oComp = Nothing
set oTDSE = Nothing
This code is executing successfully but when we check publishing queue component is getting failed with error The item tcm:34-20615-16-v0 does not exist.
Same code is working fine when we are publishing the component to staging in earlier activity.
The problem is that while in the script you are publishing dynamic version (-v0) of component. As publishing is asynchronous operation, item is not published straightaway, but publish transaction is created (which is linking to dynamic version).
After this, your script is done and item get checked-in. Now, publisher is starting with processing your publish transaction and discovers that there's no dynamic version anymore, hence your exception.
When publish activity is not last, publisher has enough time to get dynamic version of an item.
Workaround can be to wait for publish transaction to complete in your automatic activity, or do something with OnCheckIn event
Yes this is frequent one I faced at clients place. Especially when your last activity in workflow is automatic and Publish to Live.
Simplest way I did is:
First FinishActivity in automatic code
Then Publish workflow=false.
PublishCoreServiceClient.FinishActivity(activityInstance.Id, finishData, publishoptions);
}
//Now Publish
ComponentData component = (ComponentData)PublishCoreServiceClient.Read(componentid, publishoptions);
if (GetConfigurationValues(component, PublishCoreServiceClient))
{
PublishInstructionData publishInstructionData = new PublishInstructionData();
publishInstructionData.MaximumNumberOfRenderFailures = 100;
publishInstructionData.RollbackOnFailure = true;
ResolveInstructionData resolveInstructionData = new ResolveInstructionData();
resolveInstructionData.IncludeWorkflow = false;
resolveInstructionData.IncludeChildPublications = true;
resolveInstructionData.IncludeComponentLinks = true;
publishInstructionData.ResolveInstruction = resolveInstructionData;
RenderInstructionData renderInstructionData = new RenderInstructionData();
publishInstructionData.RenderInstruction = renderInstructionData;
List<string> ItemToPublish = new List<string>();
ItemToPublish.Add(component.Id);
if (!String.IsNullOrEmpty(Utilities.LIVE_URI))
{
PublicationTargetData pubtarget = (PublicationTargetData)PublishCoreServiceClient.Read(Utilities.LIVE_URI, publishoptions);
List<string> target = new List<string>();
target.Add(pubtarget.Id);
PublishCoreServiceClient.Publish(ItemToPublish.ToArray(), publishInstructionData, target.ToArray(), PublishPriority.Normal, publishoptions);
Logger.Debug("ElapsedMilliseconds Publish [" + _watch.ElapsedMilliseconds + " ms]");
}
Issue is resolved after setting activateWorkflow parameter of Publish method to False.
We had the same error and we have solved it by sending the component to publish with a few seconds delay:
Call oComp.Publish("tcm:0-1-65538", False, False, True, dateAdd("s",10,Now))

How do I create a unit test that updates a record into database in asp.net

How do I create a unit test that updates a record into database in asp.net
While technically we don't call this a 'unit test', but an 'integration test' (as Oded explained), you can do this by using a unit testing framework such as MSTest (part of Visual Studio 2008/2010 professional) or one of the free available unit testing frameworks, such as NUnit.
However, testing an ASP.NET web project is usually pretty hard, especially when you've put all you logic inside web pages. Best thing to do is to extract all your business logic to a separate layer (usually a separate project within your solution) and call that logic from within your web pages. But perhaps you’ve already got this separation, which would be great.
This way you can also call this logic from within your tests. For integration tests, it is best to have a separate test database. A test database must contain a known (and stable) set of data (or be completely empty). Do not use a copy of your production database, because when data changes, your tests might suddenly fail. Also you should make sure that all changes in the database, made by an integration test, should be rolled back. Otherwise, the data in your test database is constantly changing, which could cause your tests to suddenly fail.
I always use the TransactionScope in my integration tests (and never in my production code). This ensures that all data will be rolled back. Here is an example of what such an integration test might look like, while using MSTest:
[TestClass]
public class CustomerMovedCommandTests
{
// This test test whether the Execute method of the
// CustomerMovedCommand class in the business layer
// does the expected changes in the database.
[TestMethod]
public void Execute_WithValidAddress_Succeeds()
{
using (new TransactionScope())
{
// Arrange
int custId = 100;
using (var db = new ContextFactory.CreateContext())
{
// Insert customer 100 into test database.
db.Customers.InsertOnSubmit(new Customer()
{
Id = custId, City = "London", Country = "UK"
});
db.SubmitChanges();
}
string expectedCity = "New York";
string expectedCountry = "USA";
var command = new CustomerMovedCommand();
command.CustomerId = custId;
command.NewAddress = new Address()
{
City = expectedCity, Country = expectedCountry
};
// Act
command.Execute();
// Assert
using (var db = new ContextFactory.CreateContext())
{
var c = db.Customers.Single(c => c.Id == custId);
Assert.AreEqual(expectedCity, c.City);
Assert.AreEqual(expectedCountry, c.Country);
}
} // Dispose rolls back everything.
}
}
I hope this helps, but next time, please be a little more specific in your question.

Resources