WebDrawer - Electronic document 'Not found'

It might be the case that some CM users have permission to view a Record metadata but not the electronic document. In this case they will get a message like the one below when they open a document link.

not found.PNG

Improving the message

It may be that you do not wish to inform the user that there is an electronic document to which to do not have access, but if you do here is how to make the message more informative.

  1. in the WebDrawer folder edit the file \RazorPages\NotFound.cshtml

  2. replace the content of the <div> with code similar to that below.

The Code

@if (Model != null && Model.ResponseStatus != null)
    if (Model.ResponseStatus.ErrorCode == "101")
<p>The Document cannot be displayed due to access restrictions.  
  To request access to this document please contact the <a href="mailto:rm@acme.com">Records Administrator</a></p>
} else {
    <p>Page not found!</p>

The Result

The ‘Not Found’ page should now look similar to this.



Spending most of my days alone in an office I love the occasions when I get to meet some of the people who use CM. One of the most enjoyable experiences is hearing directly from people who need a particular fix/feature and then being able to go back to my office and make that happen.

I, along with various other CM developers, will be at Realize this year, I will not venture beyond Melbourne but members from the dev team will be at all the Realize events.

Come along, tell us your stories and shine a light into the long lonely months in the office.

Deleting files left behind by the Office Integration

The scenario:

  1. open Excel

  2. create a worksheet

  3. check the worksheet into CM using the Office Integration

  4. close Excel

  5. a temp file is left behind in Documents\Micro Focus CM

  6. the file is deleted the next time you open Excel (or another Office application).

The problem

The scenario described above occurs because Excel retains a handle on the file until it has completed closing, at which point the Office Integration has been unloaded and is unable to delete the file. Other Office applications (e.g. Word) release the file before they close allowing the Office Integration to delete the temp file.

A Workaround

While a future version of CM may contain a solution for this problem a work-around available today is to run a powershell script from the windows task scheduler to delete left over files.

The Script

The script below finds all files scheduled for deletion in the managed docs XML file, deletes them and removes the entry from the XML file.

$filePath = $env:APPDATA + "\Micro Focus\Content Manager\OfficeIntegration\managedDocs"

[xml]$cn = Get-Content $filePath

$cn.ArrayOfManagedDocument.ManagedDocument | ? { $_.DeleteMe -eq $true } | % { 
    Remove-Item $_.Path


The schedule

Not being an admin expert I will not tell you how to configure this script to run for all (or selected) users but I can tell you how I configured it in Windows Task Scheduler. Calling a Powershell script from Windows Task Scheduler is described in this post. In short:

  1. create a task

  2. add an action where program equals powershell.exe and arguments look something like this: -ExecutionPolicy Bypass c:\scripts\file_cleanup.ps1

  3. add a trigger

The Trigger

The trigger could be several of the available options, I chose ‘At log on’ as it was least likely to come into conflict with my use of Office.

WebDrawer Viewing error

The scenario:

  1. Open WebDrawer using Google Chrome

  2. find a record with a PDF document

  3. View it (using the Trapeze viewer


4. Select the Document link


5. You will see this error


The Fix

To fix this:

  1. open the file views\shared\menuButton.cshtml

  2. look for this line:

    <a tabindex="-1" href="~/@menuItem.Value">@menuItem.Key</a>
  3. Change it to this:

    <a tabindex="-1" target="_top" href="~/@menuItem.Value">@menuItem.Key</a>

Dashboards and business intelligence

Last week I took some time out of my schedule to experiment with Power BI. While Power BI can access many data sources, including a JSON/REST web service such as the ServiceAPI, it is simplest to access data sources for which a connector exists. This led me to experiment with Power Query custom connectors.

The connector I show in the video below is not production ready but is far enough along to demonstrate its viability. Before proceeding I would like some feedback from anyone who might use this to answer questions like:

  • Is Power BI of interest?

  • What data would you want to extract from CM in Power BI?

  • What sort of Dashboards / Reports would you produce?

One nice thing about a custom connector is that it could quite easily be backwards compatible, so would work with existing CM implementations.

If you have any interest in this space and want to see this experiment go further send me a private message at the CM Forum.

Hello, World!

Deleting in the ServiceAPI

Strangely enough there are multiple paths via which you might choose to delete a Record in the ServiceAPI. When looking back on how this choice was made I tend to agree with Elizabeth Bennett that a good memory is unpardonable, but, is it a problem that there are multiple ways to delete a Record?

Delete via Record post

The first method is to use a service action, that is to post JSON similar to that below to the Record endpoint. Not only does this attempt to delete the Record but also allows you to make updates to properties (and save) the Record prior to delete being called.

    "Uri": 9000000544,
    "DeleteRecord": {
        "DeleteRecordDeleteContents": false

Delete via delete service

The other way to delete is simply to post to the delete service using a URL like this:


And the winner is…

Avoid the first option and use the second option. Why? The first option, in addition to deleting the Record, does all of the processing required when updating properties and fields. This is unnecessary when you are deleting and is likely to cause errors. The second option avoids all the unnecessary pipeline and simply deletes the Record making it much more robust.

Loading the .Net SDK

If you relied on us loading HP.HPTRIM.SDK.dll into the GAC you may have noticed that the 93 installer no longer does this, which has eliminated a number of messy deployment issues for us. For more information see the Microsoft guidelines re GAC installation.

The good news

A key benefit of GAC installation was the ability to write version agnostic SDK applications, the good news is that you can still do this. All you need to do is intercept the assembly loading pipeline and you can specify that HP.HPTRIM.SDK.dll gets loaded from the location specified in the registry.

DataPort Custom Formatter

By default DataPort imports a tab delimited file. What is less well known is that you can write your own formatter to import an arbitrary file format. In this sample I import a very simple XML file. Even though the XML file itself is simple it is a little more complex to import than a tab delimited file due to the fact that it does not follow the essentially columnar layout of a tab delinted file.

We also have the code for our standard tab delimited formatter in the GitHub repo.

BTW, you may hear in the background the happy sounds of my 2 year old son playing in the backyard, enjoy!

Microsoft Office Web Add-ons

Recently I posted re some research we have done into Google Docs and Gmail integration. This post shows the result of similar research into building add-ons for Microsoft Office Online.

Online versions of Office applications are different to the native versions in some not so subtle ways, for example in Office Online your document is saved very frequently, also collaborative editing is encouraged, this impacts the design of a Content Manager add-on.

Currently we have a our SharePoint integration and the Web Client Office Online integration, so any potential Office Web add-on needs to be designed to solve a meaningful business problem. It is even conceivable that Email Link might provide a sufficient server side solution.

If you have an interest in Office add-ons get in touch via the usual channels.

Make it faster!

Recently I spent several hours chasing 280 milliseconds that I was convinced should not have been there.  The ServiceAPI URL I was calling looked like this:


After hours tuning the ServiceAPI code I managed to tweak a 20 millisecond improvement, still I was sure there was more. I looked once more at the URL and made one small improvement, to this:


Suddenly I had eliminated my extra 260 milliseconds!

Can you spot the difference?  Previously I had an incorrect property name, RecordOwner should have been RecordOwnerLocation. Why is this a problem? If the ServiceAPI does not recognise a property it checks to see if it is a valid 'additional field' for this Record.  Multiply the time to check this by 100 (the page size) and there is the 260 milliseconds.

The moral

260 milliseconds is not a lot but in a web service environment it adds up so be careful to to include invalid property names in the properties parameter.

Now I am off to see if the 'additional field' code can be optimised.