I am using Tridion Core Service to get all the Components published from a publication on a specific target. The code is as below.Since there can be lot of components and the result obtained using this code contains all items, Is there any way to narrow down the results (like providing ItemType and recursive as false).
var filter = new PublishTransactionsFilterData
{
PublicationTarget = new LinkToPublicationTargetData { IdRef = targetId },
ForRepository = new LinkToRepositoryData { IdRef = GetPublication(publicationId)},
BaseColumns = ListBaseColumns.IdAndTitle,
};
XElement t= Instance.GetSystemWideListXml(filter);
var v = t.Elements().Where(k => k.Attribute("ItemType").Value == "16");
First of all your code will always return null, as because of ListBaseColumns.IdAndTitle there will be no ItemType attribute. The only way to narrow down the results are properties you can find on PublishTransactionsFilterData, which are:
EndDate, StartDate to search only inside this timestamp
Priority, if you know it
PublishedBy, if you know who published it
All the rest is post filtering, which is also ok. You can filter on everything you have in XML. Sample XML looks like this:
<tcm:Item ID="tcm:0-241-66560" Title="page" Allow="24576" Deny="67108864" Icon="T64L0P0" ItemType="64" ItemID="tcm:2-72-64" State="4" StateChangeDate="2013-03-11T14:53:55" Publication="Test" PublicationTarget="Local" ItemPath="\Test\New Structure Group" Action="0" ScheduleDate="" UserId="tcm:0-11-65552" User="domain\user" Priority="4" Managed="0" />
You can postfilter on any of the attributes
Related
I would like to create a .NET page residing on the CMS server that shows all components that are based on a specific Schema(tcm:3-3-8) and from a specific Publication(tcm:0-3-1) including BluePrinted and Localized items, but only if they have the value "http://www.google.com" for the field "URL" in that Schema.
Is this possible, without using the search service as this is rather slow and unreliable?
Your search might be slow because of not indexing the search collection.
You should do indexing the search collection on regular intervals for better and fast results.
That's an expensive operation to do because of the cost of opening each individual component to check the value of a field, but certainly do-able.
Get the schema object
Get a list of components that use this schema (WhereUsed on the schema with filter on ItemType = component)
Open each component and check the value for the field(s), add to a List<Component> if it matches
Display list (possibly using a ASP.NET GridView)
I have not had any chance to test it, but something like this
Common common = new Common();
TDSE tdse = new TDSE();
ListRowFilter ComponentFilter = tdse.CreateListRowFilter();
Schema schema = (Schema)common.getObject("tcm:126-238630-8", ItemType.ItemTypeSchema);
ComponentFilter.SetCondition("ItemType", ItemType.ItemTypeComponent);
ComponentFilter.SetCondition("Recursive", true);
XDocument doc = common.ReadXML(schema.Info.GetListUsingItems(ListColumnFilter.XMLListID, ComponentFilter));
List<Component> MatchedComponents = new List<Component>();
XmlNamespaceManager NS = new XmlNamespaceManager(new NameTable());
NS.AddNamespace("tcm", "http://www.tridion.com/ContentManager/5.0");
NS.AddNamespace("Content", "uuid:4432F3C3-9F3E-45E4-AE31-408C5C46E2BF");
foreach (XElement component in doc.XPathSelectElements("/tcm:ListUsingItems/tcm:Item", NS))
{
Component comp = common.getComponent(component.Attribute("ID").Value);
XDocument compDoc = common.ReadXML(comp.GetXML(XMLReadFilter.XMLReadData));
foreach (XElement compNode in compDoc.XPathSelectElements("/tcm:Component/tcm:Data/tcm:Content/Content:Content/Content:feederUrl", NS))
{
MatchedComponents.Add(comp);
}
}
I'm trying to understand the purpose of the BasedOnSchemas option in the OrganizationalItemItemsFilterData filter.
The documentation clearly states:
"Gets or sets the BasedOnSchemas condition to return only items that are using the given schemas"
So it should be possible to only retrieve components of a specific schema, right?
here's my code:
LinkToSchemaData[] schemaLinks = new[] {
new LinkToSchemaData { IdRef = "tcm:113-362325-8" }
};
OrganizationalItemItemsFilterData filter =
new OrganizationalItemItemsFilterData();
filter.BaseColumns = ListBaseColumns.Extended;
filter.ItemTypes = new ItemType[] { ItemType.Component };
filter.Recursive = true;
filter.BasedOnSchemas = schemaLinks;
XElement items = client.GetListXml("tcm:113-14192-2", filter);
The XElement items will however, contain multiple types of components, not only those of schema tcm:113-362325-8
How can I retrieve only those components that are based on my schema?
Using both BasedOnSchemas and Recursive = true is not supported. Remove the the recursiveness and you'll find that the schema filter works.
If you want to get a "recursive" list of all Components for a certain Schema, consider doing a WhereUsed on the Schema.
GetListXml("tcm:5-59-8", new UsingItemsFilterData())
I want to get the all fields along with type/datatype of the metadata fields of a Metadata schema.
I have written below sample code to achieve the functionality and I am able to get Name, Description etc but could not find any property with type/dataType. If anyone of you have any idea, please suggest...
var client = new SessionAwareCoreService2010Client();
client.ClientCredentials.Windows.ClientCredential.UserName = "myUserName";
client.ClientCredentials.Windows.ClientCredential.Password = "myPassword";
client.Open();
if (client.State == System.ServiceModel.CommunicationState.Opened)
{
var schemaUri = "tcm:1-47-8";
var fields= client.ReadSchemaFields(schemaUri, true, new ReadOptions());
var fieldName = fields.MetadataFields[0].Name;
}
To know the type of a field, you only need to examine the .NET type of the field.
I typically use an "is" check, but you can also call GetType if you want.
For example:
var client = new SessionAwareCoreService2010Client();
client.ClientCredentials.Windows.ClientCredential.UserName = "myUserName";
client.ClientCredentials.Windows.ClientCredential.Password = "myPassword";
client.Open();
if (client.State == System.ServiceModel.CommunicationState.Opened)
{
var schemaUri = "tcm:1-47-8";
var fields= client.ReadSchemaFields(schemaUri, true, new ReadOptions());
foreach (var field in fields.MetadataFields)
{
if (field is SingleLineTextFieldDefinitionData)
{
// Do something specifically for single-line text fields
}
}
}
The ReadSchemaFields method exposes only the definition of the fields. So it is essentially a wrapper around the properties you enter while you define the field in a schema.
The Content and Metadata are exposed by ComponentData.Content and ComponentData.Metadata respectively. But those are exposed as XML strings, so you will have to do your own parsing of them.
If you (understandably) don't feel like that, have a look at this helper class: http://code.google.com/p/tridion-practice/wiki/ChangeContentOrMetadata
You might also want to read my answer to this question: Updating Components using the Core Service in SDL Tridion 2011
I need to get the list of localized items of a publication programatically using coreservice in tridion. Could any one suggest me.
I would use the GetListXml method and specify a BluePrintChainFilterData filter object.
var subjectId = "[TCM Uri of your item]";
var filter = new BluePrintChainFilterData
{
Direction = BluePrintChainDirection.Down
};
var subjectBluePrintChainList = coreServiceClient.GetListXml(subjectId, filter);
You then still need to verify the localized items from the received list.
This wasn't in my original answer, and probably isn't complete because I don't take into account namespaces, but the following would work to select the localized (not shared) items.
var localizedItems = subjectBluePrintChainList.Elements("Item")
.Where(element => "false".Equals(element.Attribute("IsShared").Value, StringComparison.OrdinalIgnoreCase));
The only way I know is to use search functionality:
var searchQuery = new SearchQueryData();
searchQuery.BlueprintStatus = SearchBlueprintStatus.Localized;
searchQuery.FromRepository = new LinkToRepositoryData{IdRef = "tcm:0-5-1"};
var resultXml = ClientAdmin.GetSearchResultsXml(searchQuery);
var result = ClientAdmin.GetSearchResults(searchQuery);
I'm using the Tridion Core Service (Tridion 2011 SP1) to retrieve a list of keywords for given Category ID.
CoreService2010Client client = new CoreService2010Client();
XElement xmlCategoryKeywords = client.GetListXml(category.Id,
new KeywordsFilterData());
This returns what seems to be a flat XML structure representing our taxonomy which is 4 levels deep.
The documentation details an approach for working with this:
var categoryKeywords = xmlCategoryKeywords.Elements().Select(element =>
element.Attribute("ID").Value).Select(id => (KeywordData)client.Read(id, null)
);
foreach (KeywordData keyword in categoryKeywords)
{
Console.WriteLine("\t Keyword ID={0}, Title={1}", keyword.Id, keyword.Title);
}
However this will only list each Keyword. The KeywordData object contains property ParentKeywords so it would be possible to build the hierarchy in memory.
Is it possible to retrieve XML from the Core Service with a hierarchical structure? Or an easier way to work with this data?
One way is to use TaxonomiesOwlFilterData:
string publicationId = "tcm:0-3-1";
var filter = new TaxonomiesOwlFilterData();
filter.RootCategories = new[] {new LinkToCategoryData{ IdRef = "tcm:3-158-512"},};
var list = ClientAdmin.GetListXml(publicationId, filter);
As you see it is called on publication, but you can narrow it down to one or more categories. It will return you scary XML list that you can further process like this:
XNamespace tcmc = publicationId + "/Categories#";
XNamespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
XNamespace tcmt = "http://www.tridion.com/ContentManager/5.2/Taxonomies#";
var taxonomyTree = new Dictionary<string, List<string>>();
var keywordNodes = list.Descendants(tcmc + "cat");
foreach (var keywordNode in keywordNodes)
{
var parents = new List<string>();
var parentNodes = keywordNode.Descendants(tcmt + "parentKeyword");
if (parentNodes.Count() > 0)
{
foreach (var parentNode in parentNodes)
{
parents.Add(parentNode.Attribute(rdf + "resource").Value);
}
}
taxonomyTree.Add(keywordNode.Attribute(rdf + "about").Value, parents);
}
As a result you will get unordered list of your keywords and corresponding parents that you can further process as you like. Item that has no parent is obviously a parent keyword. It might not be the most beatiful solution, but at least you will need only one call to server and not read each keyword.
You could process each branch, level by level. Here's some code I've been playing around with that does that:
CoreService2010Client client = new CoreService2010Client("basicHttp_2010");
KeywordsFilterData keywordsDataFilter = new KeywordsFilterData()
{
BaseColumns = ListBaseColumns.IdAndTitle,
IsRoot = true
};
UsingItemsFilterData usingItemsFilter = new UsingItemsFilterData()
{
BaseColumns = ListBaseColumns.IdAndTitle,
ItemTypes = new[] { ItemType.Keyword },
InRepository = new LinkToRepositoryData() { IdRef = "tcm:0-1-1" }
};
XElement parents = client.GetListXml("tcm:1-272-512", keywordsDataFilter);
foreach (XElement parent in parents.Descendants())
{
// Do something with the parent (top level) KW
XElement children = client.GetListXml(parent.Attribute("ID").Value, usingItemsFilter);
foreach (XElement child in children.Descendants())
{
// Do something with the child KW
}
}
I've found in the past that processing a flat list in to a hierarchy (in my case a list of all SGs in a Publication) created a massive overhead compared to processing a branch at a time. Of course I should caveat that by saying that I tried that with an old (early 5.x) version of Tridion so things may have improved since then.
Tridion 2011 SP1 comes with a new CoreService EndPoint. CoreService 2011. Its recommended to use the latest endpoint. Latest endpoint has new functionalists also bug fixes. SP1 also has a default coreservice client proxy that u can use directly in your code.