Micro Focus Content Manager SDK 10.0
Advanced Topics

Different ways to fetch a TrimMainObject

Accessing a Record is discussed briefly in the help but there are a variety of ways to get a TrimMainObject.

Object constructor by Name

As discussed in the help use the Name or Uri to instantiate the object.

Code example

This example fetches a Classification by name.

Classification classification = new Classification(database, "Accommodation - Domestic - General");
Console.WriteLine(classification.Title);
@ Classification
For Records that have a Classification of

Object name properties

As can be seen a certain knowledge of the object type is required to fetch by name. For example, the name property for each object type is different. For most object types the name property is Name. Here is a list of those object types where that rule does not apply:

Object Types Name Property
ActionDef ActionName
AgendaItem Number
Alert Description
Classification Title
Communication Description
Consignment Number
ConsignmentApprover Record
ConsignmentIssue Record
History EventDescription
Location SortName
MinuteItem Description
OfflineRecord Title
Record Number
RecordAction ActionName
Request Record
SavedSearch FullName
ScheduledTask Description
SharePointItem UniqueId
Space Number
TodoItem Description
UserLabel FullName
ZipCode Postcode

Even with this information there are still things to be aware of, for example:

Database find methods

There are a number of methods available on the Database object. They key difference between these and the object constructors is that these return null if the object cannot be found, while the object constructors throw an exception. These methods are:

Code samples

// fetch by Record Number
Record record1 = database.FindTrimObjectByName(BaseObjectTypes.Record, "REC_1") as Record;
Console.WriteLine(record1.Title);
// Fetch by Uri
Record record2 = database.FindTrimObjectByUri(BaseObjectTypes.Record, 9000000001) as Record;
Console.WriteLine(record2.Title);
// Fetch by URN
Record record3 = database.FindTrimObjectByURN("trim:I1/rec/9000000001") as Record;
Console.WriteLine(record3.Title);
BaseObjectTypes
The BaseObjectTypes enum
Definition: BaseObjectTypes.cs:16

Note: The URN property is typically used when you need to persist a database- and object-type independent identifier for the object.

TrimMainObjectSearch

TrimMainObjectSearch may be used in place of the constructor and Database methods of fetching an object. One benefit when fetching by name, where the name may not be unique, is that you can respond better to the various scenarios.

Code sample

// Find all Locations where the name starts with David
TrimMainObjectSearch locationSearch = new TrimMainObjectSearch(database, BaseObjectTypes.Location);
locationSearch.SelectByPrefix("david");
foreach (Location location in locationSearch)
{
Console.WriteLine(location.FullFormattedName);
}
// Find the Locations with the Uri 1
locationSearch = new TrimMainObjectSearch(database, BaseObjectTypes.Location);
locationSearch.SelectByUris(new long[] { 1 });
foreach (Location location in locationSearch)
{
Console.WriteLine(location.FullFormattedName);
}
// Find all Locations who are direct members of the group 'Adelaide'
locationSearch = new TrimMainObjectSearch(database, BaseObjectTypes.Location);
locationSearch.SelectThoseWithin(new Location(database, "Adelaide"));
foreach (Location location in locationSearch)
{
Console.WriteLine(location.FullFormattedName);
}
// Find all Locations where the sort name is david
// You may want to return an error if there is more than one result, if you are looking for a unique Location
locationSearch = new TrimMainObjectSearch(database, BaseObjectTypes.Location);
locationSearch.SetSearchString("locSortName:david");
foreach (Location location in locationSearch)
{
Console.WriteLine(location.FullFormattedName);
}

Document access alternatives

Overview

There are a variety of ways to retrieve an electronic document attached to a Record (or other object type). These are:

Record.GetDocument()

Record.GetDocument() is the primary way to get an electronic document from a Record and will be used for most .NET SDK applications. It allows the user to fetch a copy of the document from the document store to their local hard drive. If the document is already in the users cache then it will be retrieved from the cache, rather than from the store.

Checkout without getting the document

You may wish to set the Record edit status to 'checked out', without fetching the Record. In this case simply call GetDocument() with a null outputDocumentName. For example:

Record record = new Record(database, "REC_430");
record.GetDocument(null, true, null, null);

DocumentPathInClientCache

This method of fetching documents was added to improve support for web services. The advantage it has over Record.GetDocument() is that it does not require you to store a new copy of the document, copied from your local cache to the path in the outputDocumentName parameter. If document store caching is disabled, this property will be empty, unless your application is running as a service or web service.

Example

TrimApplication.SetAsWebService("c:\\hptrim\\mytest");
using (Database database = new Database())
{
database.Id = "I1";
database.WorkgroupServerName = "local";
database.TrustedUser = "itu_tenduser";
database.Connect();
Record record = new Record(database, "REC_430");
if (!record.IsDocumentInClientCache)
{
record.LoadDocumentIntoClientCache();
}
Console.WriteLine(record.DocumentPathInClientCache);
}

DocumentPathInWGSCache

If your workgroup server has document caching enabled, an application running on that server (not on a client machine) can use the DocumentPathInWgsCache property to get the location of the document in the workgroup server cache. The benefit of doing so is that the workgroup server cache can be pre-emptively loaded, so that the document can be present in the cache before it is first asked for.

Example

Record record = new Record(database, "REC_430");
Console.WriteLine(record.DocumentPathInWGSCache);

DownloadNotifier

DownloadNotifier implements a download mechanism with two advantages over other document access methods:

  1. it starts returning bytes almost immediately, rather than you having to wait until the entire file has been copied from the document store, and
  2. you may start part way through a file.

DownloadNotifier is of particular use in web applications, where you will want to start returning the file to the end user as soon as possible, rather than waiting until the entire file has been fetched from the document store, and also where you may wish to have a resumable download.

Example

long count = 20922;
byte[] buffer = new byte[20922];
Record record = new Record(database, "REC_43");
long bytesSoFar = 0; // use bytesSoFar to start part way through the file for a partial download
using (DownloadNotifier notifier = new DownloadNotifier(database, count, bytesSoFar))
{
notifier.OnChunkAvailable += (byte[] chunk, long chunkPos, long chunkLen, bool lastChunk) =>
{
// Write the chunk to an output stream here.
};
ExtractDocument extractDoc = record.GetExtractDocument();
extractDoc.DoExtract(null, true, false, null);
}
@ ExtractDocument
For Document Extraction

Other object types

While this document has focused primarily on Records other main and child objects also implement ITrimDocument, and therefore also support electronic documents. These objects will at least support the Client Cache method of getting the document, and may also implement a method returning an ExtractDocument (such as LocationEAddress )

Localised strings

When building a user interface based on the Content Manager SDK, it can be helpful to use the captioned and localised strings provided by Content Manager. Most strings used by Content Manager are available from the SDK in a way that will account for the user's language choice and changes to captions.

TrimMessages

TrimApplication.GetMessage() is used to fetch error and other messages from Content Manager. These messages will automatically account for any custom captions.

Code Sample

//This code will display the following string, replacing the word 'record' with the custom caption for 'record' if set.
//
// This record has alternate contents. You can use the Show Alternate Contents button if you wish to load these relationships.
string message = TrimApplication.GetMessage(database, MessageIds.bob_recHasAltContentsMsg);
Console.WriteLine(message);

Captions

Many custom strings can be fetched from an objects Caption property. This is particularly important when captions have been customised.

Enum captions

This code displays the caption (and plural caption) of the DisposalType enum followed by the captions for each EnumItem.

TRIM.SDK.Enum myEnum = new TRIM.SDK.Enum(AllEnumerations.DisposalType, database);
Console.WriteLine(myEnum.Caption);
Console.WriteLine(myEnum.CaptionPlural);
foreach (EnumItem enumItem in myEnum.GetItemArray(null, true))
{
Console.WriteLine(enumItem.Caption);
}
A helper class that allows you to iterate through enum item values and access captions for them.
Definition: Enum.cs:16
Definition: ApiHost.cs:5
AllEnumerations
Definition: AllEnumerations.cs:13
Definition: ApiHost.cs:5

Property Captions

The PropertyDef class supplies captions for object properties. Use the code below to get all writable property captions for the Location object. Other static methods to get PropertyDef objects are:

foreach (PropertyDef propertyDef in PropertyDef.GetWriteableProperties(BaseObjectTypes.Location, database))
{
Console.WriteLine(propertyDef.Caption);
}

Search Clause Captions

Search clause captions work similarly to property definitions except that you must get a list of SearchClauseIds, and then construct a SearchClauseDef from the SearchClauseId. The sample below writes the captions for all Activity search clauses.

foreach (SearchClauseIds clauseId in SearchClauseDef.GetAllSearchClauseIds(BaseObjectTypes.Activity, database))
{
SearchClauseDef clauseDef = new SearchClauseDef(clauseId, database);
Console.WriteLine(clauseDef.Caption);
}

Menu items

Menus in Content Manager are available for inspection as well. Once again a definition object, CommandDef, provides metadata such as the menu or status bar string for each menu item.

MenuPopup menuPopup = MenuPopup.GetMenuForTrimObject(database, BaseObjectTypes.Classification);
foreach (var menuItem in menuPopup)
{
if (menuItem is CommandDef)
{
CommandDef cdef = menuItem as CommandDef;
Console.WriteLine(cdef.GetMenuEntryString(BaseObjectTypes.Classification));
}
}

FormDefinition

FormDefiniton is particularly useful for Records where it is possible to set custom captions on the various properties on the Record entry form. As with the other definition objects, FormDefinition (and its related classes) are useful for much more than captions, and in fact they are the foundation from which the Content Manager Web Client forms are built.

RecordType recordType = new RecordType(database, "Document");
FormDefinition formDefinition = recordType.RecordPropertiesFormDefinition;
for (uint pageCount = 0; pageCount < formDefinition.PageCount; pageCount++)
{
PageDefinition pageDefinition = formDefinition.GetPage(pageCount);
Console.WriteLine(pageDefinition.Caption);
for (uint itemCount = 0; itemCount < pageDefinition.ItemCount; itemCount++)
{
PageItemDefinition itemDefinition = pageDefinition.GetItem(itemCount);
Console.WriteLine(itemDefinition.Caption);
}
}
@ RecordType
For Records that have a Record Type of

Fetching LookupSet Items

In Content Manager 8.2, LookupSet items were freed from the restrictions of being of type TrimChildObject. This means that a lookup set item (LookupItem) is now a TrimMainObject, at the same level as the lookup set itself. Why was this done? Mainly to allow for large lookup sets. The parent/child relationship among Content Manager objects imposes practical limits on the number of children a main object can have.

Example: Adding a new LookupItem

To add a new LookupItem, instantiate it using the LookupSet as the constructor parameter.

LookupSet lookupSet = new LookupSet(database, 9000000000);
LookupItem lookupItem = new LookupItem(lookupSet);
lookupItem.Name = "My Test";
lookupItem.Save();

Example: Fetching lookup items

You can get a list of lookup items, just as you would any other main object type (e.g. record or location), using TrimMainObjectSearch, as seen here.

TrimMainObjectSearch lookupItemSearch = new TrimMainObjectSearch(database, BaseObjectTypes.LookupItem);
lookupItemSearch.SetSearchString("set:9000000000");
foreach (LookupItem item in lookupItemSearch)
{
Console.WriteLine(item.Name);
}

Create a Record using manual numbering

When a Record Type has a Record Number containing both manual and automatic portions, user interaction is required to create the Record. This can be done in the SDK by first suggesting a number (to get the auto-generated portion), and then replacing the manual portion with input from the user.

Example: Manual Record Number

string manualPortion = "TRY-THIS";
RecordType rt = new RecordType(database, "RECORD TYPE NAME");
Record rec = new Record(rt);
rec.Title = "test";
string suggestedNumber = rec.GetSuggestedNumber(true);
suggestedNumber = suggestedNumber.Replace("zzz-aaaa", manualPortion);
rec.LongNumber = suggestedNumber;
rec.Save();