<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.3">Jekyll</generator><link href="http://hprm.info/feed.xml" rel="self" type="application/atom+xml" /><link href="http://hprm.info/" rel="alternate" type="text/html" /><updated>2023-05-15T06:03:16+00:00</updated><id>http://hprm.info/feed.xml</id><title type="html">Focus on Content Manager</title><subtitle>Web services, Web Drawer, SDK and more...</subtitle><entry><title type="html">Troubleshooting Teams - setting validDomains</title><link href="http://hprm.info/Teams-integration-valid-domains/" rel="alternate" type="text/html" title="Troubleshooting Teams - setting validDomains" /><published>2023-05-15T00:00:00+00:00</published><updated>2023-05-15T00:00:00+00:00</updated><id>http://hprm.info/Teams-integration-valid-domains</id><content type="html" xml:base="http://hprm.info/Teams-integration-valid-domains/">&lt;p&gt;If Content Manager specifies a URL for the Web Client then the Teams integration will include this in the tab links when adding the integration to a channel.  If the full web domain is not specified in the Teams integration manifest that was uploaded to install the integration then the process of adding a tab to a channel will fail.&lt;/p&gt;

&lt;p&gt;In this example the domain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intranet.acme.com&lt;/code&gt; must be included in the list of valid domains.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/cm_url.png&quot; alt=&quot;System options&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;validDomains&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;intranet.acme.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name></name></author><category term="teams" /><summary type="html">If Content Manager specifies a URL for the Web Client then the Teams integration will include this in the tab links when adding the integration to a channel. If the full web domain is not specified in the Teams integration manifest that was uploaded to install the integration then the process of adding a tab to a channel will fail.</summary></entry><entry><title type="html">Troubleshooting Teams / OpenID Connect server connections</title><link href="http://hprm.info/Teams-integration-auth-troubles/" rel="alternate" type="text/html" title="Troubleshooting Teams / OpenID Connect server connections" /><published>2023-05-12T00:00:00+00:00</published><updated>2023-05-12T00:00:00+00:00</updated><id>http://hprm.info/Teams-integration-auth-troubles</id><content type="html" xml:base="http://hprm.info/Teams-integration-auth-troubles/">&lt;p&gt;A vital element of the Content Manager Teams integration is the ServiceAPI Azure AD authentication setup.  For the authentication to work it is essential that the ServiceAPI server be able to communicate with AzureAD, which may require web proxy configuration, adding the server to a white list or some other network configuration.  If the server is unable to communicate to Azure AD you may get some confusing errors in the ServiceAPI logs.  The PowerShell script below mimics the code used by the ServiceAPI when it first connects to the ServiceAPI allowing you to verify that the basic requirement of connectivity is met before proceeding to other troubleshooting.&lt;/p&gt;

&lt;p&gt;To use this code: 
 1) create a ps1 file in the ServiceAPI bin folder
 2) copy the script below to the file,
 3) in the Azure portal, open an App registration, got to Endpoints and copy the ‘OpenID Connect metadata document,
 4) replace the value in $url in the script with your ‘OpenID Connect metadata document’ URL
 5) run the script, NOTE: ensure that you are running the script logged in as the same user selected for the ServicAPI identity&lt;/p&gt;

&lt;p&gt;You should see displayed the metadata for your app registration.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ps1&quot;&gt;$assemblyPath1 = (Join-Path $PSScriptRoot &quot;Microsoft.IdentityModel.Protocols.dll&quot;)
$assemblyPath2 = (Join-Path $PSScriptRoot &quot;Microsoft.IdentityModel.Protocols.OpenIdConnect.dll&quot;)
$assemblyPath3 = (Join-Path $PSScriptRoot &quot;Microsoft.IdentityModel.Tokens.dll&quot;)


try {
Add-Type -Path $assemblyPath1
Add-Type -Path $assemblyPath2



$retriever = New-Object Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever
$url = &quot;https://login.microsoftonline.com/08363ee4-6592-4325-9d5a-5a25e00d482b/v2.0/.well-known/openid-configuration&quot;

$configurator = New-Object -TypeName Microsoft.IdentityModel.Protocols.ConfigurationManager[Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfiguration] @($url, $retriever)

$getConfig = $configurator.GetConfigurationAsync()

$getConfig.Wait()

$getConfig.Result

} 
catch [System.AggregateException]
    {
     $_.Exception.ToString() | out-host

      $_.Exception.Handle({
            param($ex)

            $ex.Message | out-host
           
            return $false
            
        })

    }
catch [System.Exception]
{
    $_.Exception.ToString() | out-host
} 

&lt;/code&gt;&lt;/pre&gt;</content><author><name></name></author><category term="teams" /><category term="openid" /><summary type="html">A vital element of the Content Manager Teams integration is the ServiceAPI Azure AD authentication setup. For the authentication to work it is essential that the ServiceAPI server be able to communicate with AzureAD, which may require web proxy configuration, adding the server to a white list or some other network configuration. If the server is unable to communicate to Azure AD you may get some confusing errors in the ServiceAPI logs. The PowerShell script below mimics the code used by the ServiceAPI when it first connects to the ServiceAPI allowing you to verify that the basic requirement of connectivity is met before proceeding to other troubleshooting.</summary></entry><entry><title type="html">Powershell confidential client</title><link href="http://hprm.info/powershell-confidential-client/" rel="alternate" type="text/html" title="Powershell confidential client" /><published>2023-02-09T00:00:00+00:00</published><updated>2023-02-09T00:00:00+00:00</updated><id>http://hprm.info/powershell-confidential-client</id><content type="html" xml:base="http://hprm.info/powershell-confidential-client/">&lt;p&gt;Use the &lt;a href=&quot;https://github.com/content-manager-sdk/Community/tree/master/Samples/ServiceAPI/Powershell&quot;&gt;sample&lt;/a&gt; code to connect to the ServiceAPI from powershell using the confidential client authentication flow.&lt;/p&gt;
&lt;iframe src=&quot;https://player.vimeo.com/video/797172274?app_id=122963&amp;amp;wmode=opaque&quot; width=&quot;640&quot; height=&quot;400&quot; frameborder=&quot;0&quot; title=&quot;Power BI&quot; allow=&quot;autoplay; fullscreen&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;</content><author><name></name></author><category term="serviceapi" /><summary type="html">Use the sample code to connect to the ServiceAPI from powershell using the confidential client authentication flow.</summary></entry><entry><title type="html">Partial file download</title><link href="http://hprm.info/Content-Range-download/" rel="alternate" type="text/html" title="Partial file download" /><published>2023-02-08T00:00:00+00:00</published><updated>2023-02-08T00:00:00+00:00</updated><id>http://hprm.info/Content-Range-download</id><content type="html" xml:base="http://hprm.info/Content-Range-download/">&lt;p&gt;I was asked recently about downloading files from the ServiceAPI using the Content-Range header to support chunked downloads.  I was sure that this was supported but it was not working. After some hours of digging I found a problem that caused normal document downloads to ont recognize Content-Range, oddly enough the service to return multiple documents as a zip was working.&lt;/p&gt;

&lt;h3 id=&quot;multiple-files-as-a-zip&quot;&gt;Multiple files as a zip&lt;/h3&gt;
&lt;p&gt;The standard download URL may be used to return documents for multiple records as a zip by using comma separated URI’s, for example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;https://mydev.dev/ServiceAPI/Record/9000000001,9000000002/File/document
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If any of the records do not have a document attached they will be ignored.&lt;/p&gt;

&lt;h3 id=&quot;custom-download-addin&quot;&gt;Custom download addin&lt;/h3&gt;
&lt;p&gt;If you need to use chunked downloads another solution may be to install the &lt;a href=&quot;https://github.com/content-manager-sdk/Community/tree/master/Samples/ServiceAPI/CSharp/PartialDownloadPlugin&quot;&gt;sample plugin&lt;/a&gt; in the samples.  When added to the ServiceAPI this will add a service called ‘PartialDownload’ that support the Content-Range header.  Some code that can be used as a starting point to test this can be found in the getDocumentInChunks sample in the &lt;a href=&quot;https://github.com/content-manager-sdk/Community/tree/master/Samples/ServiceAPI/CSharp/ConsoleServiceAPIClient&quot;&gt;ServiceAPI console app sample&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><category term="serviceapi" /><summary type="html">I was asked recently about downloading files from the ServiceAPI using the Content-Range header to support chunked downloads. I was sure that this was supported but it was not working. After some hours of digging I found a problem that caused normal document downloads to ont recognize Content-Range, oddly enough the service to return multiple documents as a zip was working.</summary></entry><entry><title type="html">Record Type sorting</title><link href="http://hprm.info/Record-Type-Sort-Order/" rel="alternate" type="text/html" title="Record Type sorting" /><published>2022-11-24T00:00:00+00:00</published><updated>2022-11-24T00:00:00+00:00</updated><id>http://hprm.info/Record-Type-Sort-Order</id><content type="html" xml:base="http://hprm.info/Record-Type-Sort-Order/">&lt;p&gt;The Content Manager user options allow you to sort Record Types, how do you achieve this using the SDK?&lt;/p&gt;

&lt;p&gt;First you want to find our whether the option to display your favourite Record Types first is switched on, and if not to switch it on (or off).&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var options = new TrimUserOptionSet(db, UserOptionSetIds.SelectRecordType);
var favFirst = options.GetPropertyBool(PropertyIds.SelectRecordTypeUserOptionsFavoritesFirst);

Console.WriteLine(favFirst.ToString());

options.SetPropertyBool(PropertyIds.SelectRecordTypeUserOptionsFavoritesFirst, !favFirst);
options.Save();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next you will want to make one or more Record Types a favourite for this user and then move it up or down in the list.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var recordType = new RecordType(db, &quot;Document&quot;);
recordType.AddToFavorites();
recordType.ChangePositionWithinFavorites(LabelPositionChange.MoveUp);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Retrieving the Record Types in the order specified can be achieved through either the SDK or the ServiceAPI. Using the SDK requires a TrimMainObjectSearch constructed using the RecordTypeFilter enum, for example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var recordTypeSearch = new TrimMainObjectSearch(db, RecordTypeFilter.AllForCreate);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The ServiceAPI requires the parameter recordTypeFilter, for example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;https://acme.com/ServiceAPI/RecordType?q=all&amp;amp;purpose=2&amp;amp;recordTypeFilter=2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name></name></author><category term="dotnet-sdk" /><summary type="html">The Content Manager user options allow you to sort Record Types, how do you achieve this using the SDK?</summary></entry><entry><title type="html">Form Definitions</title><link href="http://hprm.info/Data-Entry-Form/" rel="alternate" type="text/html" title="Form Definitions" /><published>2022-10-11T00:00:00+00:00</published><updated>2022-10-11T00:00:00+00:00</updated><id>http://hprm.info/Data-Entry-Form</id><content type="html" xml:base="http://hprm.info/Data-Entry-Form/">&lt;p&gt;For anyone wanting to build a user interface in Content Manager the FormDefinition class is essential.  Some of the object types allow a form defintionto be created from a the FormDefintion contructor for new or existing objects.  For records might also choose to use the RecordType.RecordPropertiesFormDefinition property.&lt;/p&gt;

&lt;p&gt;In this very simple code I use the form definition to determine the mandatory fields for a particular RecordType.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var recordType = new RecordType(db, &quot;Document&quot;);

var formDef = recordType.RecordPropertiesFormDefinition;

for (uint pageCount = 0; pageCount &amp;lt; formDef.PageCount; pageCount++)
{
    var page = formDef.GetPage(pageCount);

    for (uint itemCount = 0; itemCount &amp;lt; page.ItemCount; itemCount++)
    {
        var prop = page.GetItem(itemCount);
        Console.WriteLine($&quot;{prop.Caption} - {prop.IsMandatory}&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name></name></author><category term="dotnet-sdk" /><summary type="html">For anyone wanting to build a user interface in Content Manager the FormDefinition class is essential. Some of the object types allow a form defintionto be created from a the FormDefintion contructor for new or existing objects. For records might also choose to use the RecordType.RecordPropertiesFormDefinition property.</summary></entry><entry><title type="html">Documentation updates</title><link href="http://hprm.info/updates-to-docs/" rel="alternate" type="text/html" title="Documentation updates" /><published>2022-07-14T00:00:00+00:00</published><updated>2022-07-14T00:00:00+00:00</updated><id>http://hprm.info/updates-to-docs</id><content type="html" xml:base="http://hprm.info/updates-to-docs/">&lt;p&gt;Microsoft made some big updates to the Azure Powershell CLI which necessitated changes to the zero footprint office setup script.  For those staying on with the older version of the CLI we have retained the older setup script, both can be found in the &lt;a href=&quot;https://content-manager-sdk.github.io/Community/101/zero_teams.html#zero_teams_script&quot;&gt;documentation&lt;/a&gt;.
We have filled one of the gaps in our documentation with a new document on how to configure ADFS OpenID for native Content Manager, once again see the &lt;a href=&quot;https://content-manager-sdk.github.io/Community/101/oidc.html#oidc_adfs_native&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><category term="azure-ad" /><category term="office-integration" /><summary type="html">Microsoft made some big updates to the Azure Powershell CLI which necessitated changes to the zero footprint office setup script. For those staying on with the older version of the CLI we have retained the older setup script, both can be found in the documentation. We have filled one of the gaps in our documentation with a new document on how to configure ADFS OpenID for native Content Manager, once again see the documentation.</summary></entry><entry><title type="html">Teams and Office Installer</title><link href="http://hprm.info/teams-and-office-installer/" rel="alternate" type="text/html" title="Teams and Office Installer" /><published>2022-02-22T00:00:00+00:00</published><updated>2022-02-22T00:00:00+00:00</updated><id>http://hprm.info/teams-and-office-installer</id><content type="html" xml:base="http://hprm.info/teams-and-office-installer/">&lt;p&gt;As at the date of my publishing this post Content Manage 10.1 is still to be released but those in the beta program will have access to a preview in the near future. To assist in installing the zero footprint Office and Teams integrations there is a &lt;a href=&quot;https://raw.githubusercontent.com/content-manager-sdk/Community/master/docs/files/101/az_install.ps1&quot;&gt;powershell script&lt;/a&gt; to create the Azure AD app and the related Office365 manifests.  In the video below I demonstrate using this script.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest&quot;&gt;Azure CLI&lt;/a&gt; is a pre-requisite for using this script.&lt;/p&gt;

&lt;h3 id=&quot;protected-apis&quot;&gt;Protected APIs&lt;/h3&gt;

&lt;p&gt;To use the Microsoft APIs to retrieve either channel posts or group chats you need special permission from Microsoft, this may be request using their &lt;a href=&quot;https://docs.microsoft.com/en-us/graph/teams-protected-apis&quot;&gt;request form&lt;/a&gt;.  You will need to supply the ID of the Azure AD app created for the Teams Integration as well as the reason you need organisation wide access to posts, probably for compliance purposes.&lt;/p&gt;

&lt;iframe src=&quot;https://player.vimeo.com/video/680202809?app_id=122963&amp;amp;wmode=opaque&quot; width=&quot;640&quot; height=&quot;400&quot; frameborder=&quot;0&quot; title=&quot;Power BI&quot; allow=&quot;autoplay; fullscreen&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;</content><author><name></name></author><category term="azure-ad" /><category term="office-integration" /><summary type="html">As at the date of my publishing this post Content Manage 10.1 is still to be released but those in the beta program will have access to a preview in the near future. To assist in installing the zero footprint Office and Teams integrations there is a powershell script to create the Azure AD app and the related Office365 manifests. In the video below I demonstrate using this script.</summary></entry><entry><title type="html">Object Notifier</title><link href="http://hprm.info/Object-Notifier/" rel="alternate" type="text/html" title="Object Notifier" /><published>2021-08-09T00:00:00+00:00</published><updated>2021-08-09T00:00:00+00:00</updated><id>http://hprm.info/Object-Notifier</id><content type="html" xml:base="http://hprm.info/Object-Notifier/">&lt;p&gt;The Object Notifier is an event based system to notify you when objects in Content Manager have changed, it can be used in a ServiceAPI application to proactively update your UI to refleect changes in the data, this &lt;a href=&quot;https://github.com/content-manager-sdk/Community/tree/master/Samples/WebDrawer/ObjectNotifier&quot;&gt;sample&lt;/a&gt; implements the Object Notifier in the WebDrawer Record search results.&lt;/p&gt;
&lt;iframe src=&quot;https://player.vimeo.com/video/583728780?app_id=122963&amp;amp;wmode=opaque&quot; width=&quot;640&quot; height=&quot;400&quot; frameborder=&quot;0&quot; title=&quot;Power BI&quot; allow=&quot;autoplay; fullscreen&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;</content><author><name></name></author><category term="serviceapi" /><category term="webdrawer" /><summary type="html">The Object Notifier is an event based system to notify you when objects in Content Manager have changed, it can be used in a ServiceAPI application to proactively update your UI to refleect changes in the data, this sample implements the Object Notifier in the WebDrawer Record search results.</summary></entry><entry><title type="html">Sample OpenAPI Definition File</title><link href="http://hprm.info/Sample-OpenAPI-Definition-File/" rel="alternate" type="text/html" title="Sample OpenAPI Definition File" /><published>2021-08-02T00:00:00+00:00</published><updated>2021-08-02T00:00:00+00:00</updated><id>http://hprm.info/Sample-OpenAPI-Definition-File</id><content type="html" xml:base="http://hprm.info/Sample-OpenAPI-Definition-File/">&lt;p&gt;The swagger definition file that is auto-generated by the ServiceAPI swagger UI is not particularly useful due to its large size and complexity, in fact it often causes swagger tools to crash.  For this reason it is better to handcraft an OpenAPI definition file to respresent the portions of the ServiceAPI you need.  The &lt;a href=&quot;https://github.com/content-manager-sdk/Community/tree/master/Samples/ServiceAPI/Connectors/OpenAPI&quot;&gt;sample&lt;/a&gt; is in the samples repo, the following video is a run through of making a change to the file and generating test code.&lt;/p&gt;
&lt;iframe src=&quot;https://player.vimeo.com/video/581966028?app_id=122963&amp;amp;wmode=opaque&quot; width=&quot;640&quot; height=&quot;400&quot; frameborder=&quot;0&quot; title=&quot;Power BI&quot; allow=&quot;autoplay; fullscreen&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;</content><author><name></name></author><category term="serviceapi" /><summary type="html">The swagger definition file that is auto-generated by the ServiceAPI swagger UI is not particularly useful due to its large size and complexity, in fact it often causes swagger tools to crash. For this reason it is better to handcraft an OpenAPI definition file to respresent the portions of the ServiceAPI you need. The sample is in the samples repo, the following video is a run through of making a change to the file and generating test code.</summary></entry></feed>