Release Notes

SelectByTemplate Auto-Save

posted Jan 2, 2019, 10:46 AM by Eric Patrick   [ updated Jan 2, 2019, 10:47 AM ]

The GenericObject class in QBO offers a SelectByTemplate method to enforce repeatability. Two recent changes were introduced that can have unexpected consequences for existing installations:
  • {Table}Template and {Table}TemplateID may be used as synonyms for Template and TemplateID
  • SelectByTemplate no longer calls Save when detecting a new instance of a class

QBO has always supported the concept of templated repeatability as:
  • One generic object per parent
  • One active generic object per parent, and
  • Many generic objects per parent
For example, one can defined a DecisionTemplate called "Invoice Client" as one active per parent where calling 

Decision/Save?Object=Organization&ObjectID=1&Template=Invoice Client

will result in:
  • If an existing Invoice Client workflow exists and is open, it will be "reused" (no new workflow is created),
  • If an existing Invoice Client workflow exists and is not open, a new Invoice Client workflow will be created, or
  • If no existing Invoice Client workflow exists, a new Invoice Client workflow will be created
However, the following method signatures did not abide by repeatability rules:

Decision/Save?Object=Organization&ObjectID=1&DecisionTemplate=Invoice Client

This exposed a bug in the ITemplate.CreateInstance pattern, where the {Table}TemplateID property was being set, instead of TemplateID, causing repeatability to be ignored when creating generic objects from workflows.

The fix for this now supports methods signature using {Table}Template or {Table}TemplateID, but in turn exposed another bug:


triggers a Save call.  Normally, this save call has no effective impact, because SelectByTemplate is almost always called from Save anyway. However, when adding a Message from the UI, Message/Merge is called, which in turn calls Message/SelectByTemplate, which triggered a Save on the Merge, even if a user never clicks Save.

Given the broad impact of removing the SelectByTemplate Save call, this change has been feature-switched:

qbo.Application.Properties.Settings.SelectByTemplateAutoSave = false

If this change results in undesirable behavior of a given installation, take the following steps:
  • From Design > Modules > Matrix > Settings, change the qbo.Application.Properties.Settings.SelectByTemplateAutoSave setting to true
  • Notify Quandis support of your specific use case so our architecture team can consider workarounds

Object Queue Performance Update

posted Dec 19, 2018, 10:27 AM by Greg Kent   [ updated Dec 19, 2018, 12:25 PM ]

ObjectQueue has been updated to address performance issues. The following objects have been updated:
  • dbo.ObjectQueue - Specialized indexes for CurrentQueue and CallbackQueue usage
  • ObjectQueue/PopItem - Optimized to reduce/eliminate deadlocks
 ObjectQueue contention was causing deadlocks for:
  • Callback processing
  • CurrentQueue processing
which resulted in stalled workflows and overall database contention.

Please ensure the above updates are deployed together to avoid any performance issues.

Workflow Advanced Step Update

posted Dec 19, 2018, 10:17 AM by Greg Kent   [ updated Dec 19, 2018, 12:24 PM ]

DecisionStep.cs has been updated so that Advanced Steps fully support async processing:
  • Advanced Steps where a Custom Query is specified
  • Advanced Steps where a Custom Query is specified and Batch is specified
By converting to async, this allows for the Method Signature of the Custom Query (DecisionStepTemplate.Method) to be invoked async. This also allows for batch steps to wire async.

Threading is now managed by using SemaphoreSlim class and a set number of threads must be specified. qbo.Decision settings has been extended to contain:

BatchStepTheadCount - Default thread count for processing advanced steps. Value is defaulted to 5 threads.

ITemplate Update

posted Dec 19, 2018, 10:01 AM by Greg Kent

The following QBO3 ITemplate method signatures have been extended:

CreateInstance(GenericObject parent, IDictionary<string, object> parameters)

CreateInstanceAsync(GenericObject parent, IDictionary<string, object> parameters)

Both have been extended to include a Parent parameter that allows for accessibility to the Parent for optional actions. 

This is a breaking changeAll classes that implement ITemplate  must be re-complied against this change to work. Do not deploy qbo.Application.dll without also deploying all other modules.

All modules that implement ITemplate have been updated.

The first use case was a bug fix in DecisionTemplate to address stalled workflows:
  • DecisionStep/StartTemplateAsync launches a Decision
  • Child Decision processing and completing before the parent DecsionStep could be properly bound
  • DecisionTemplate/CreateTemplateAsync was extended to persist information to the Parent to ensure bindings were in place before the child Decision processed

Case Insensitive QBO URLs

posted Dec 11, 2018, 10:47 AM by Eric Patrick   [ updated Jan 11, 2019, 1:02 PM ]

QBO has been updated to support cases insensitive URLs and parameters. While not a breaking change, the change is deep enough that it includes a feature switch to enable/disable the functionality: qbo.Application.Properties.Settings.CaseSensitiveMethodSignature, which defaults to false.

To leverage the feature switch, instead of calling:

new Dictionary<string, object>()
code should instead call:

new Parameters()

The Parameters class constructor sets the StringComparer based on the CaseSensitiveMethodSignature. Beyond that, the functionality is equivalent to IDictionary<string, object>.

The changes to enable this include:
  • Created application setting CaseSensitiveMethodSignatures, defaults to true
  • Introduced a Parameters: Dictionary<string, object> that sets case sensitivity based on CaseSensitiveMethodSignatures
  • Introduced IConfigurationName for configuration elements that implement Name properties
  • DbConfigurationElementCollection: this[string name] will resolve names in a case insensitive format for IConfigurationName items
  • AbstractObject: new Dictionary<string, object> => new Parameters()
  • Decorated several configuration classes with IConfigurationName
  • Updated Functions to handle type resolution of Parameters correctly
  • Created IgnoreCaseFacts test
  • Added code to abide by Accept headers for Output
  • Updated other tests as needed to correct bugs in the test code.

qbo.Security.PasswordCompliance - Plugin Extensible Password Rules Enforcement

posted Nov 30, 2018, 5:14 PM by Cameron Watt

The Security module has been updated with a robust "password rules enforcement" piece under the namespace qbo.Security.PasswordCompliance. You can use these features out-of-the-box, using the default settings.

Key Features:
  • When a password is to be changed, the piece runs checks against a set of rules, customized in a new app setting for qbo.Security -> PasswordRuleSet.
  • Render a custom human readable version of these rules as instructions for the user, customized in another app setting in qbo.Security -> PasswordRulesText.
  • Extend and add new rule functionality"plugin style" via a new qbo.Security.PasswordCompliance project.
  • Responsive UI feedback on why a password was rejected.
  • The plugin project qbo.Security.PasswordCompliance is completely optional, and only needs to be included if more functionality is desired.
  • The updates are aligned with the latest in trunk as of the date of this post, however there are a few points to check that this will not break your build.
    1.  SecurityWeb, MortgageWeb and ApplicationWeb must be up to date to deploy this change. Login.ForcePasswordChange.xslt, BrokerProfile.Account.xslt and Theme.Core.xslt respectively have been updated with a few JavaScript tweaks to call the correct functionality.
    2.  Ensure you are able to compile new C# 7.0 features.
Successful Deployment checks:
  • Person, or another security module, has the settings PasswordRuleSet and PasswordRulesText.
  • Person.config contains a statement CheckPasswordReuse and InsertPassword, and does NOT contain SetPassword.
  • An attempt to change a password returns informative rule error text, or succeeds.
New tests have been added to qbo.Security.Tests in relation to this new functionality.

MVC-Style Custom Routing

posted Nov 30, 2018, 12:46 PM by Eric Patrick   [ updated Dec 14, 2018, 5:51 AM ]

QBO3 now supports custom routes, including RESTful-compliant routes.

This is a breaking change: the HttpHandler and HttpAsyncHandler have been tweaked, and all .ashx handler must be re-complied against this change to work. Do not deploy qbo.Application.dll without also deploying all other modules.

Custom routes are defined in CustomRoutes.config, and the web.config must be modified to include these entries:

<section name="Routes" type="qbo.Application.Configuration.CustomRouteConfiguration, qbo.Application"/>
<Routes configSource="config\CustomRoutes.config" />

Standard routes include:

<?xml version="1.0"?>
    <CustomRoute Name="Default-1-Queue" Url="api/{class}/queue/{operation}"/>
    <CustomRoute Name="Default-2-Parent" Url="api/{Object}/{ObjectID:int}/{class}/{operation}"/>
    <CustomRoute Name="Default-3-Singleton" Url="api/{class}/{operation}/{id:int}"/>
    <CustomRoute Name="Default-4-Default" Url="api/{class}/{id:int}"/>
    <CustomRoute Name="Default-5-Any" Url="api/{class}/{operation}"/>
    <CustomRoute Name="Default-6-Documents" Url="documents/{operation}" MethodSignature="Attachment/{operation}"/>
    <CustomRoute Name="Default-8-Upload" Url="documents/uploadchunk" MethodSignature="Attachment/UploadChunk" Handler="qbo.AttachmentWeb.Attachment, qbo.AttachmentWeb"/>

Errors from Incomplete Deployments

If you deploy qbo.Application.dll without rebuilding associated web project, you will get an error along these lines:

Field not found: 'qbo.Application.HttpAsyncHandler.QueueOperation'.

To fix this error, recompile and redeploy all projects.


posted Nov 27, 2018, 2:15 PM by Eric Patrick

The qbo.Application module has been extended to support an IEncryptionKey interface and associated configuration. The Credential class has been extended to leverage the IEncryptionKey settings to symmetrically encrypt or decrypt Credential.Password.  The Credential behavior is:
  • If no EncryptionKey is configured, serialization of Credential will include Password in clear text.
  • If any EncryptionKey is configured, serialization of Credential will include EncryptedPassword (symmetrically encrypted Password), and not include Password.
This means that the Credential when persisted to ConfigurationEntry will contain an EncryptedPassword string that must be decrypted with the same key used to encrypt the Password.

The qbo.Encryption.Amazon (found in the qbo.Amazon solution) can be used to leverage an AWS KMS key for encryption and decryption.

Newtonsoft.JSON Nuget Package Updates

posted Nov 26, 2018, 2:30 PM by Eric Patrick

The qbo.Core.sln is being updated to include references to Newtonsoft.Json version 11+.  This mandates an updated to web.config:

    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="" newVersion="" />

If you miss this update, you will received an error message along these lines:

FileLoadException: Could not load file or assembly 'Newtonsoft.Json, Version=, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'; or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.

Developers should check any plugin-based solutions to ensure the current version of Newtonsoft.Json is referenced (currently v11.0.2). If you fail to update a plugin solution, and deploy it after deploying core, you will deploy an older version of Newtonsoft.Json (e.g. v10), causing the reverse of the above error. 

Decision Repeatability

posted Nov 15, 2018, 12:59 PM by Chad Boyer

The below has been resolved.  Made changes to GenericObject and updated the ApplicationTests project with both this new functionality and old functionality to ensure coverage.

The gist of this was that if you passed DecisionTemlateID in the code was looking for just TemplateID (Similar pattern with DecisionTemplate and Template).  The code now allows {Table}Template to be added as a parameter and does a proper SelectByTemplate to add the underlying object.

Decision repeatability not being respected.
This issue was noticed within SLS, not sure if it is happening elsewhere.

UI Decision/Save
Find a DecisionTemplate that is set to one active per parent.
Navigate to a loan and create a decision using the template noted above.  Ensure it is not complete or canceled.
Attempting to create another decision should not succeed but it does.

The following method signature is used within SLS to evaluate a matrix then create a decision using parameter substitution.  Running it multiple times in a row should not create multiple decisions based on repeatability settings, but it does.
Here's the method with the appropriate values.

1-10 of 57