Monday, June 11, 2012

Performing Search Queries with the Core Services

One of the most covered topics about Tridion and its integration points are the Core Services and how it can be used to create and read/filter data in the Content Manager. However, one other important aspect in the Content Manager is the possibility to create Virtual Folders and perform Advanced Search queries.

In this topic I will cover some of the Search Query capabilities available in the Core Services.

SearchQueryData Class

 

This class is the base for all the Search Query operation available in the Core Services. The following fields are the most important ones.

Author: The results will return items created by the specified author.

filter.Author = new LinkToUserData() { IdRef="[tcm id]" };

Title: The results will return items containing the specified title or part of it.

filter.Title = "*title*";

Note that I am adding some asterisks at the beginning and at the end. Those asterisks are wild cards, this filter will return items which contains the word "title" at any part of the Title property.

SearchIn: The results will return items located in the specified item, for instance a folder.

filter.SearchIn = new LinkToIdentifiableObjectData() { IdRef="[Folder Tcm Id]" };

FullTextQuery:The results will return any item which xml representation contains the property value. Be careful while using this property since it could affect your search query performance.

filter.FullTextQuery = "Foot Note";

BasedOnSchemas: The results will return items by checking the actual field values based on schemas. For instance if you have an schema called "Note" and it has a field called "TopNote", you can search for items based on the schema "Note" where the "TopNote" field has the value "*First*".

BasedOnSchemaData basedSchemaNote = new BasedOnSchemaData();
basedSchemaNote.Schema = new LinkToSchemaData() { IdRef = "tcm:5-198-8" };
basedSchemaNote.Field = "TopNote";
basedSchemaNote.FieldValue = "*First*";

Note that you can specify wild cards as asterisks.

ItemTypes: The results will return items by checking the acutal ItemType.

filter.ItemTypes = new ItemType[] { ItemType.Component, ItemType.ComponentTemplate };

IsPublished: The results will return items by checking if they have been published.

filter.IsPublished = true;

Note that this property will just specify if the item is published or not. It does not specify where it was published, if you want to get that information you will need to filter the returned items by using a PublishingListFilterData filter or the GetListPublishInfo methods.

FromRepository: Normally used to specify the Publication where the search should take place.
ResultLimit: Restrict the number of returned results.

Sample of a Search Query


CoreServiceClient channel = new CoreServiceClient("basicHttp_2011");

SearchQueryData filter = new SearchQueryData();
filter.FullTextQuery = "Sample";
filter.ItemTypes = new ItemType[] { ItemType.Component };


BasedOnSchemaData basedSchema1 = new BasedOnSchemaData();
basedSchema1.Schema = new LinkToSchemaData() { IdRef = "tcm:5-198-8" };
basedSchema1.Field = "title";
basedSchema1.FieldValue = "*title*";


BasedOnSchemaData basedSchema2 = new BasedOnSchemaData();
basedSchema2.Schema = new LinkToSchemaData() { IdRef = "tcm:5-198-8" };
basedSchema2.Field = "title";
basedSchema2.FieldValue = "FootNote3";


filter.BasedOnSchemas = new BasedOnSchemaData[] { basedSchema1, basedSchema2 };
XElement results = channel.GetSearchResultsXml(filter);
for (IEnumerator<XElement> e = results.Descendants().GetEnumerator(); e.MoveNext(); ) {
    Console.WriteLine("{Title: {0}}", e.Current.Attribute(XName.Get("Title")).Value);
}

The sample above will return all the items which have "Sample" as part of their xml representations, also it is checking if the title field contains the text "title" anywhere in the field or the exact "FootNote3" word.

Friday, June 1, 2012

Consuming SDL Tridion Core Services from Adobe Flex - Part 2

In the first part Consuming SDL Core Services from Adobe Flex - Part 1 I covered the foundation of the interoperability between SDL Tridion and Adobe Flex. In this second part I will cover more advanced topics like effectively consuming data available in the Content Manager. This topic will cover read and filtering operations.

Sending soap requests to the Core Services


The web services based on soap implementation available in flex is pretty simple and does not allow you to do sophisticated requests that are easy to do in languages like C#. However, it gives you complete control on the soap messages being transferred between the flex application and the Core Services. The main issue with this approach is that must know the exact soap syntax that the Core Services understand in order to process the request. If you refer to my other article Inspecting SDL Tridion Core Services SOAP messages you will find a tool that allows you to inspect the soap messages being transferred between a C# client and the Core Services, in this post I will use the same syntax for my flex client. The following soap body would be the one used to send a request for a "Where Used" operation.

<GetListXml xmlns="http://www.sdltridion.com/ContentManager/CoreService/2011">
    <id>tcm:5-6</id>
    <filter xmlns:d4p1="http://www.sdltridion.com/ContentManager/R6"
              xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
              i:type='d4p1:UsingItemsFilterData'>
        <d4p1:ItemTypes>
              <d4p1:ItemType>Component</d4p1:ItemType>
        <d4p1:ItemTypes>
    </filter>
</GetListXml>

 

Receiving soap responses from the Core Services


Flex supports several response formats (the result formats must be specified during the request), in this topic I will cover the most important ones in order to retrieve information from the core services.

The e4x format will instruct the parser to return the soap response as it is and to don't apply any kind of serialization. This format is really important when we retrieve xml lists. This also solves a serialization problems related with the Core Services because all the xml list responses are defined as xsd:Any in the xml schema and Flex cannot serialize them.

The object format will instruct the parser to return a serialized soap response. It will return an ObjectProxy instance from there we can retrieve all the information as properties. For instance for a component we can retrieve the content and metadata of a component using the following code.

var content:String = result.Content.toString();
var metadata:String = result.Metadata.toString();

 

Reading a tridion item


As shown in the code snippets below I am defining two methods one to retrieve the Tridion Item as a serialized object and the other one as an XML stream. Note that the operation name passed to the channel.getOperation method must match with the one defined in the Core Services WSDL.

public function ReadItem(id:String, success:Function, error:Function):void {
    var op:Operation = Operation(channel.getOperation("Read"));
    op.addEventListener(ResultEvent.RESULT, success);
    op.addEventListener(FaultEvent.FAULT, error);
    op.resultFormat = "object";
    op.send(id);
}

public function ReadItemXml(id:String, success:Function, error:Function):void {
    var op:Operation = Operation(channel.getOperation("Read"));
    op.addEventListener(ResultEvent.RESULT, success);
    op.addEventListener(FaultEvent.FAULT, error);
    op.resultFormat = "e4x";
    op.send(id);

 

Retrieving an xml list

This code snippet will retrieve a "Where Used' list.

public const CORESERVICE_NS:String = "http://www.sdltridion.com/ContentManager/CoreService/2011";
public const TRIDION_NS:String = "http://www.sdltridion.com/ContentManager/R6";
public const XSDI_NS:String = "http://www.w3.org/2001/XMLSchema-instance";
public const TRIDION_5_NS:String = "http://www.tridion.com/ContentManager/5.0";

public function GetListUsingItems(id:String, itemTypes:Array, success:Function, error:Function):void {
    var op:Operation = Operation(channel.getOperation("GetListXml"));
    op.addEventListener(ResultEvent.RESULT, success);
    op.addEventListener(FaultEvent.FAULT, error);
   
    var param:XML =
        <GetListXml xmlns={CORESERVICE_NS}>
            <id>{id}</id>
            <filter xmlns:d4p1={TRIDION_NS} xmlns:i={XSDI_NS} i:type='d4p1:UsingItemsFilterData'>
                <d4p1:ItemTypes />
            </filter>

        </GetListXml>
   
    var itemTypesXML:XMLList = param.descendants(new QName(TRIDION_NS, "ItemTypes"));
    for (var index:String in itemTypes) {
        var type:String = itemTypes[index];
        itemTypesXML.appendChild(<ItemType xmlns={TRIDION_NS}>{type}</ItemType>);
    }
   
    op.resultFormat = "e4x";
    op.send(param);
}

 

Retrieving a system wide list

This code snippet will retrieve the list of publications in the system

public const CORESERVICE_NS:String = "http://www.sdltridion.com/ContentManager/CoreService/2011";
public const TRIDION_NS:String = "http://www.sdltridion.com/ContentManager/R6";
public const XSDI_NS:String = "http://www.w3.org/2001/XMLSchema-instance";
public const TRIDION_5_NS:String = "http://www.tridion.com/ContentManager/5.0";

public function GetListPublicationsXml(success:Function, error:Function):void {
    var op:Operation = Operation(channel.getOperation("GetSystemWideListXml"));
    op.addEventListener(ResultEvent.RESULT, success);
    op.addEventListener(FaultEvent.FAULT, error);
   
    var param:XML =
        <GetSystemWideListXml xmlns={CORESERVICE_NS}>
            <filter xmlns:d4p1={TRIDION_NS} xmlns:i={XSDI_NS} i:type='d4p1:PublicationsFilterData' />
        </GetSystemWideListXml>
   
    op.resultFormat = "e4x";
    op.send(param);
}