Looks good. Yeah, casting can be tricky with regard to seeing your way from point A to point B -- I am still not used to it, especially coming from Voisual Foxpro where there is no strict typing at all.
The foreach methodology isn't really all that onerous -- there's no other way, really, to iterate through a collection using procedural programming, whether it be an array, a list of strings, or rows in a DataTable.
If you do need to do more interesting things with a list of strings (or any IEnumerable), you can take a look at LINQ and other functional programming techniques. In many situations (a true LINQer might even say "all"), a foreach loop can be replaced with a single line of code. That line might be long and complicated, but LINQ lets you do set-based manipulation of enumerable elements without needing to use an explicit iterator construct.
Dictionaries are fun as well, just remember that you can't generally use the same key twice. When it comes to storing data in .NET apps, I tend to fall back on the good ol' DataTable type, another sign of my Foxpro origins where the cursor is supreme...
Yeah, that looks about right. Just hard to know what it all means without an example. I found the type by inspecting the variable, but that documentation would have told me straight away which type to cast into and that the "Keyword" property was a list of strings containing the results I ultimately wanted.
Excellent work, and you are almost there! The trick from there is to cast the "Item" property of the field (when you know it is a Keyword) to a DocumentIndexFieldKeywords type (which is built into the DocuWare .NET platform libs). Here is a foreach loop that extends your code to get just such an object (I bold-faced the line I added):
foreach (Document doc in docs.Items)
Document document = doc.GetDocumentFromSelfRelation();
foreach (DocumentIndexField field in document.Fields)
if (field.ItemElementName.ToString() == "Keywords")
DocumentIndexFieldKeywords keywords = (DocumentIndexFieldKeywords)field.Item;
The "keywords" variable (that is of type DocumentIndexFieldKeywords) has a property called "Keyword" that is a standard List<string>. So, you can get the count of the keywords via:
and would access the first string in the List via something like:
string firstKeyword = keywords.Keyword;
That should get you where you need to be.
It is very weird that you have to instantiate a second Document object via GetDocumentFromSelfRelation() when the items in the query result are already of type Document. Not sure if that is a bug or what. But I guess when in doubt, re-pull the document from its self-relation and get everything back that you need. From there, it is just a matter of casting the right property to the right type so it can be accessed without the compiler getting cranky or a run-time error being thrown.Just FYI, but if you try the above cast on a field that is not of the Keyword type, a run-time cast exception is thrown.
Thanks for working through this! Great info!
I would also like to understand how to view Keyword values, both in the .NET environment as well as via straight Platform Service calls via non-.NET code (I can't get it to work in either -- only non-Keyword indexes come through).
I have non-.NET code that can SET keywords in a Keyword field -- just need to post correctly-formed XML (or JSON) against the resource:
I searched the Platform Service URL Reference page for any mention of "keyword" and came up empty.
It would be nice to have an example provided on how to access Keyword index types.
PS. I realized the code to set Keyword indexes probably returns the keyword values in the response. But I am not sure how to just get the keywords as they are via something like a GET instead of a POST. EDIT: I confirmed that a successful update of keywords in a Keyword field returns an XML response that DOES contain the keyword field in addition to all the "regular" fields. I also confirmed the Keyword field is NOT included if I just to a straight search for a document and get an XML result back (non-.NET code).
I am fairly certain you can do this. Start by checking out:
I set up logging for all index changes across all our file cabinets, sending the relevant information to a single table within the database (on-premise). I even wrote an auto-job in Foxpro that then accesses the data and emails me with any index changes manually performed on data (it happens very, very rarely since we got barcoding working better).
I wish I could recall the steps to setting up such logs (because it isn't exactly a trivial task), but hopefully the knowledge base or another poster can point you to a better web page (because I know there is something out there because I used it as a template for what I was trying to do).
The main spot to perform configuration and play around is under the DocuWare Admin tool, <file cabinet> --> Options --> Logging.