Release Notes 2026-09-04

Release Notes 2026-09-04

Version Information

OpenEdge Release

Version Information

OpenEdge Release

Version Information

11.7.21, 12.2.19, 12.8.9, 12.8.11, 13.0.0

Release 11.7 #89545@2026-09-04

Retirement of OpenEdge 11.7

OpenEdge 11.7 has been retired by Progress Software on April 1st 2025. In consequence we urge all customers still using OpenEdge 11 to upgrade to OpenEdge 12.2 or 12.8 as soon as possible.

We are intending to drop the official support of the SmartComponent Library for OpenEdge 11.7 during the second half of the year 2025. We will then no longer ensure that new features of the framework will be usable with OpenEdge 11.7

Customers that are concerned by this intention, should reach out to us as soon as possible, so that we can discuss about a solution.

OpenEdge 13.0 support!

We are pleased to announce that we are not aware of any issues using the SmartComponent Library on OpenEdge 13.0. We hereby declare OpenEdge 13.0 fully supported for the SmartComponent Library as of the release of February 15th 2026.

OpenEdge 12.8 support!

We are pleased to announce that we are not aware of any issues using the SmartComponent Library on OpenEdge 12.8. We hereby declare OpenEdge 12.8 fully supported for the SmartComponent Library as of the release of January 15th 2024.

OpenEdge 12.2 support!

We are pleased to announce that we are not aware of any issues using the SmartComponent Library on OpenEdge 12.2. We hereby declare OpenEdge 12.2 fully supported for the SmartComponent Library as of the release of April 09th 2020.

PASOE / OEMANAGER VS Code Extension

Our first VS Code extension is available in the VS Code marketplace: https://marketplace.visualstudio.com/items?itemName=ConsultingwerkApplicationModernizationSolutionsLtd.oemanager

The extension supports developers with PASOE related routine tasks during development:

  • checking agent or session status

  • trimming the PASOE agents

  • restarting a new agent vai the ping request

Introducing the SmartComponent Library developer forum

Got questions about using the SmartComponent Library? Wish to discuss feature requests with other users of the SmartComponent Library? To facilitate networking in the growing number of SmartComponent Library users and developers, we've added a developer forum on our new home-page. The developer forum can be found at: https://www.consultingwerk.com/support/forum

A login is required to participate in the forum. Don't be shy - create your account today!

Release Notes

Following the release of the OpenEdge 11.7 Release we have completed our testing of the SmartComponent Library on this release of Progress and are proud to announce formal support for the SmartComponent Library on OpenEdge 11.7 with the 2017-04-24 release of the SmartComponent Library. Generally we recommend customers on OpenEdge 11 to upgrade to OpenEdge 11.7 quickly. Starting the 2017-07-14 release we are supporting OpenEdge 11.7 Service Pack 1 (11.7.1).

Starting the 2015-10-09 release the Business Entity Designer will feature a start page with links to most recent release note articles on this site.

With SCL-751 we have adopted native Enums for OpenEdge 11.6. To activate this feature customers must add a definition to products.i. SCL-751 provides details for this.

With SCL-1113 we have modified the templates for SmartWindowForms and SmartTabFolderPages generated from the Business Entity Designer. We have removed the initialization of the viewer controls SmartTableIOState property (value was set to "NoDataSource" within the InitializeComponent method). Customers using their own set of templates should adopt the same fix to their templates.

New Versions of Proparse .NET Assemblies (30 December 2018)

We have updated proparse with further enhancements in this release (see https://github.com/consultingwerk/proparse/releases/tag/4.0.1.1177). Please download the .NET Assemblies ZIP file from our ESD and replace the proparse.net.dll in your environment with the latest one. The new assembly reference is:

<assembly name="proparse.net, Version=4.0.1.1177, Culture=neutral, PublicKeyToken=cda1b098b1034b24"/>

As proparse is used by our Business Entity Generator, this new version of the proparse.net Assembly is also relevant for customers not doing GUI for .NET development and require support for parsing new ABL language constructs.

This version of proparse provides additional debug information when errors are thrown from proparse.net.dll.

New Version of the Consultingwerk.SmartComponents Assemly (09 January 2019)

To support the new SmartFilterControl and the "Filter" link between the SmartFilterControl/SmartDynamciFilterControl and a SmartBusinessEntityAdapter or SmartDatasetChildAdapter we have updated the Consultingwerk.SmartComponents.dll. The new Assembly reference is:

<assembly name="Consultingwerk.SmartComponents, Version=2.2.0.49856, Culture=neutral, PublicKeyToken=10603cb31df311b3"/>

Customers need to update this Assembly in order to compile the latest releases of the SmartComponent Library.

Hybrid Realm now using IAuthenticationService

We've updated the SmartHybridRealm class used for http authentication to leverage the IAuthenticationService. It is therefor required that for AppServers requiring http Authentication (e.g. REST or Web) the correct IAuthenticationService implementation is registered (using service.xml files).

Customers relying on the previous behavior should ensure that the Consultingwerk.SmartFramework.Authentication.AuthenticationService is regsitered as the IAuthenticationService. This implementation will auhtenticate users against the password stored in the SmartUser database table.

When users with no Login Company set should be able to login using the SmartHybridRealm, it's required to set the Login Company Tennant Domain (similar to the field in the Login Company Maintenance) in the .restapplicationsettings / .applicationsettings, e.g.:

 

"DefaultAuthenticationDomain": "consultingwerk"

This is required as the Hydrid Realm Interface from Progress does not provide the domain name to the authentication method.

Web Handler overview

This is an overview of the web handlers supported by this release

defaultHandler=OpenEdge.Web.CompatibilityHandler handler1=Consultingwerk.OERA.JsdoGenericService.WebHandler.CatalogWebHandler: /Catalog/{EntityName} handler2=Consultingwerk.OERA.JsdoGenericService.WebHandler.CatalogsWebHandler: /Catalogs/{PackageName} handler3=Consultingwerk.OERA.JsdoGenericService.WebHandler.CountWebHandler: /Resource/{EntityName}/count handler4=Consultingwerk.OERA.JsdoGenericService.WebHandler.ResourceSubmitWebHandler: /Resource/{EntityName}/SubmitData handler5=Consultingwerk.OERA.JsdoGenericService.WebHandler.InvokeMethodWebHandler: /Resource/{EntityName}/{MethodName} handler6=Consultingwerk.OERA.JsdoGenericService.WebHandler.ResourceWebHandler: /Resource/{EntityName} handler7=Consultingwerk.OERA.JsdoGenericService.WebHandler.BusinessServicesWebHandler: /BusinessServices/{OutputFormat}/{PackageName} handler8=Consultingwerk.Web2.WebHandler.SmartMenuWebHandler: /SmartMenu/{MenuStructureId} handler9=Consultingwerk.Web2.WebHandler.SmartMenuStructureWebHandler: /SmartMenuStructure handler10=Consultingwerk.Web2.WebHandler.SmartRoutesWebHandler: /SmartRoutes handler11=Consultingwerk.Web2.Services.SmartViewsHandler.SmartGridWebHandler: /SmartViews/Grid/{EntityName}/{ViewName}/{DetailTemplate} handler12=Consultingwerk.Web2.Services.SmartViewsHandler.SmartGridWebHandler: /SmartViews/Grid/{EntityName}/{ViewName} handler13=Consultingwerk.Web2.Services.SmartViewsHandler.SmartGridWebHandler: /SmartViews/Grid/{CustomViewName} handler14=Consultingwerk.Web2.Services.SmartViewsHandler.SmartViewerWebHandler: /SmartViewer/Viewer/{EntityName}/{ViewName} handler15=Consultingwerk.Web2.Services.SmartViewsHandler.SmartViewerWebHandler: /SmartViewer/Viewer/{ObjectName} handler16=Consultingwerk.Web2.Services.SmartViewsHandler.SmartFormWebHandler: /SmartForm/{FormTemplate}/{EntityName}/{ViewName} handler17=Consultingwerk.Web2.Services.SmartViewsHandler.SmartFormWebHandler: /SmartForm/{FormTemplate}/{ObjectName} handler18=Consultingwerk.Web2.WebHandler.SmartMessageWebHandler: /SmartMessage/{MessageGroup}/{MessageNumber} handler19=Consultingwerk.Web2.WebHandler.GetImageWebHandler: /Image/{FileName} handler20=Consultingwerk.Web2.WebHandler.SmartValueListWebHandler: /ValueList/{ValueList} handler21=Consultingwerk.Web2.WebHandler.SmartAttachmentsWebHandler: /Attachments/{Table}/{KeyValues} handler22=Consultingwerk.Web2.WebHandler.SmartAttachmentWebHandler: /Attachment/{Guid} handler23=Consultingwerk.Web2.WebHandler.SessionContextWebHandler: /SessionContext handler24=Consultingwerk.Web2.WebHandler.ContextPropertiesWebHandler: /ContextProperties/{PropertyName} handler25=Consultingwerk.Web2.WebHandler.ContextPropertiesWebHandler: /ContextProperties handler26=Consultingwerk.Web2.WebHandler.SessionInfoWebHandler: /SessionInfo handler27=Consultingwerk.Web2.WebHandler.FileSearchWebHandler: /FileSearch/{FileName} handler28=Consultingwerk.Web2.WebHandler.ExecuteAblWebHandler: /ExecuteAbl handler29=Consultingwerk.Web2.WebHandler.SmartLanguagesWebHandler: /Languages handler30=Consultingwerk.OERA.RestResource.RestEntitiesWebHandler: /Entities handler31=Consultingwerk.OERA.Swagger.SwaggerWebHandler: /Swagger/{EntityName} handler32=Consultingwerk.OERA.Swagger.SwaggerRestEntitiesWebHandler: /SwaggerEntities/{OutputType} handler33=Consultingwerk.Web2.WebHandler.SmartTokenSecurityCheckWebHandler: /TokenSecurityCheck/{ObjectName} handler34=Consultingwerk.Web2.WebHandler.SmartTokenSecurityCheckWebHandler: /TokenSecurityCheck handler35=Consultingwerk.Web2.WebHandler.SmartEntityTableMappingHandler: /EntityTableMapping/{EntityName}/{TableName}/{UiTypeCodes} handler36=Consultingwerk.Web2.WebHandler.SmartTreeRootNodeWebHandler: /SmartViews/TreeRootNode/{rootnodeid} handler37=Consultingwerk.Web2.WebHandler.SmartTreeChildNodesWebHandler: /SmartViews/TreeChildNodes/{parentnodeid} handler38=Consultingwerk.Web2.WebHandler.SmartSecurityCheckWebHandler: /IsRestricted/{SecurityRealmCode}/{SecurityItemGuid} handler39=Consultingwerk.Web2.WebHandler.SmartFieldSecurityCheckWebHandler: /RestrictedFields/{TableName} handler40=Consultingwerk.Web2.WebHandler.GetImageNamesHandler: /ImageNames handler41=Consultingwerk.Web2.WebHandler.ExecuteQueryWebHandler: /ExecuteQuery handler42=Consultingwerk.Web2.WebHandler.TranslationProviderWebHandler: /GetTranslation

UTF-8 based deployments available

Starting August 14th 2016 we ship our source code also as UTF-8 encoded. The ZIP files ending with _utf8.zip contain the source code encoded with that code page. The source code in the remaining archives is still encoded in ISO8859-1. Also on Github there is a new branch containing the OpenEdge 11 based source code in UTF-8.

Related article (Progress K-Base): How to get Progress Developer Studio to save in UTF-8 encoding

New Feature Documentation

Download Link

http://esd.consultingwerkcloud.com/

https://github.com/consultingwerk/SmartComponentLibrary

Overview of included tickets

Image sizes can now be configured before inserting images into Word documents

Consultingwerk.Utilities.Word.WordUtility has been extended with a new SetImageSize method that configures the image dimensions used when images are inserted into a Word document via OpenXML. The method accepts the inline extent, the 2D extent, the effect extent left edge and a rotation value, mapping them onto the corresponding properties of Consultingwerk.Utilities.Support.WordHelper. Extents are expressed in English Metric Units (914400 EMU = 1 inch) and the rotation in 1/60000 of a degree; invalid values raise an InvalidParameterValueException. Because the underlying properties are static, the values apply to every subsequent image insertion in the session until they are set again, so developers should call SetImageSize immediately before each insert that needs a specific size.

Images can now replace bookmarks in Word document headers and footers

Consultingwerk.Utilities.Word.WordUtility now supports replacing a named bookmark in a Word document header or footer with an image. The new methods UpdateDocumentHeaderBookmarkImage and UpdateDocumentFooterBookmarkImage take the WordprocessingDocument, the bookmark name and the image file name; they locate the bookmark, resolve the owning HeaderPart or FooterPart, remove the placeholder text via the new RemoveRunBookmarkText method and insert the image through the new InsertHeaderParagraphImage and InsertFooterParagraphImage methods. The bookmark elements are cleaned up afterwards in the same way as for text bookmark replacement. The inserted image uses the dimensions configured through SetImageSize, so developers should set the desired size before calling these methods.

Word templates can now be validated and prepared for structured template population

Consultingwerk.Utilities.Word.WordUtility has been extended with the preparation steps required for structured Word templates such as invoices or statements. ValidateDocumentParts verifies the complete part chain of a WordprocessingDocument and raises an exception when the document cannot be read; StoreDocumentTableElements returns the template tables of the document as a List<Table>; RemoveDocumentTableElements detaches those tables while keeping them usable as clone templates; and RemoveDocumentParagraphs clears the body paragraphs while leaving headers, footers, page setup and table cell paragraphs intact. Running these four methods in sequence leaves an empty document shell ready for population. The typed descendant queries are provided by new static helpers in Consultingwerk.Utilities.Support.WordHelper, so the updated Consultingwerk.Utilities.Support.dll (version 2.5.0.0) must be in place; no changes are required in existing customer code.

Word template table structures can now be populated row by row

Consultingwerk.Utilities.Word.WordUtility now supports populating table structures in Word templates such as invoices and statements. AddTable inserts a clone of a stored template table into the document, GetTableRows returns the rows of a table, CloneRow keeps a detached copy of the template data row, and RemoveTableRows drops the template rows from a given index while keeping the header. AddTableRow then appends one populated row per data record, replacing the placeholder texts in the row cells with the values of a Dictionary<character, character>. UpdateTableCell replaces the text of an individual cell, InsertTableCellImage inserts an image into a cell, and a new AddPageBreak overload accepting a WordprocessingDocument separates consecutive documents. The methods build on the template preparation of SCL-5696 and honour the image dimensions set through SetImageSize.

Child tables of static query requests are now filled when a GenericMockDataAccess is active

When a GenericMockDataAccess was active, FetchDataByStaticQuery rerouted the call through the dynamic FetchData path and ignored the ChildTables property of the request, so unit tests received only the parent entity table filled from the mock data. Consultingwerk.OERA.BusinessEntity now appends the child tables named by an IFetchDataByStaticQueryWithChildTablesRequest to the Tables list of the generated FetchDataRequest, so the relation-driven fill populates them from the mock data-sources - matching the semantics of the generated Fill<Child>Of<Parent> methods on the real path. Unit tests using mock data-sources can now assert on child table content of static query requests without code changes.

The Browse BEDGM Files dialog now uses fuzzy matching for its search

The search field of the Business Entity Designer's "Browse BEDGM Files" dialog no longer performs a plain substring filter but scores every file name with Consultingwerk.Util.FuzzyMatchHelper:GetMatchScore. This enables Visual Studio Code style matching including prefix, substring, word and camelCase initials (for example "CBE" finds CustomerBusinessEntity.bedgm) and character subsequences. Matching files are listed best match first, while an empty search term still shows all files sorted by file name. No changes are required in customer code.

Business Entity Designer plugin lists are now stored line-break-delimited in .BusinessEntityDesignerSettings.xml

The BusinessEntityDesignerPlugins and ServerPlugins elements of .BusinessEntityDesignerSettings.xml are now written with one plugin per line and 8 spaces of indentation instead of a single long pipe-delimited string, which makes the file far easier to read, review and diff. Consultingwerk.BusinessEntityDesigner.BusinessEntityDesignerSettings still accepts the legacy pipe-delimited format as well as mixed content when loading, so existing settings files continue to load unchanged and are converted to the new format on the next save. The in-memory value of both properties remains pipe-delimited and the # prefix for disabled plugins is preserved in both directions, so no changes are required in customer code.

Interfaces implemented by the Business Entity, DatasetModel and TableModel classes can now be maintained in the Business Entity Designer

The Business Entity Designer now allows maintaining the list of interfaces implemented by the Business Entity class, the DatasetModel and the TableModel classes. A new ImplementsInterfacesPlugin adds a "Classes" ribbon group on the Source Code tab with dialogs for picking interfaces from the class path, backed by the new design properties BusinessEntity.Interfaces, DatasetModel.Interfaces and TableModel.Interfaces. During generation and regeneration the new Consultingwerk.Studio.SourceCode.ImplementsPhraseWriter synchronizes the IMPLEMENTS phrase of the generated class headers, both on the desktop and on the SmartFramework MCP Server. Classes without the corresponding design property are left untouched, so manually maintained IMPLEMENTS phrases continue to work unchanged.

REST request payloads are now also matched against the ProDataSet serialize-name

When a ProDataSet is defined with a serialize-name, the Swagger documentation and the incoming JSON payload use that name as the outermost property, while the RestEntitiesWebHandler previously looked up the payload only under the dataset's defined name - leaving the temp-tables empty. InitializeRequestArguments in Consultingwerk.OERA.Swagger / RestEntitiesWebHandler now falls back to the dataset's serialize-name when no property matching the defined name is present in the payload. Developers can therefore expose datasets with a serialize-name through the REST service interface without renaming the dataset or the method parameter. No changes required in customer code.

ServiceLoader error messages now name the failing service class when a service fails during initialization

The ServiceLoader now adds per-service error context when a service fails during its initialize phase. Previously, errors raised by IService implementations during ListService:InitializeServices were only reported with the name of the services.xml file that was being loaded, which made problems such as missing or mismatched .NET assemblies hard to diagnose. The initialize call is now wrapped so that failures are rethrown as a ServiceLoaderException naming the failing service class, and the same per-service context was added around the LoadingService event publish. No changes required in customer code; error dialogs and log entries simply contain more precise information.

ServiceContainer and ServiceLoader now support a ServiceKey for multiple keyed implementations per service type

Services can now be registered several times against the same type (typically an interface), distinguished by an optional character ServiceKey, with one registration per type flagged as the default. ServiceContainer gains keyed overloads of AddService, AddNewService, GetService, GetMandatoryService, RemoveService and IsActive, plus GetServices to retrieve all registrations of a type and RemoveServices to remove them; the keyed API is exposed through the new extension interface IKeyedServiceContainer, reachable via the new FrameworkSettings:KeyedServiceContainer property. Keys can be passed as a character value or as an enum member. ServiceLoader definition files accept the new optional ServiceKey and DefaultService elements or properties, and get-service.i and get-mandatory-service.i accept a new optional named argument ServiceKey. Existing key-less registrations, service definition files and include file usages behave exactly as before, so no changes are required in customer code.

MetaTreeview can now be rendered in MetaViewer containers with data-binding support

The dynamic rendering service has been extended so that the MetaTreeview object type can be rendered inside MetaViewer containers based on the repository definition. Repository supported instance types have been added for the MetaTreeview, including the new RootNodeType attribute stored on the repository instance. The RootNodeFilter supports data-binding, so a tree view can display data specific to the surrounding viewer, for example customer-specific nodes in a CustomerViewer. Server-side event handling and client-side event handling are available for the NodeClick and NodeDoubleClick events, allowing developers to react to tree node selection in their own code.

Fixed: A failed SaveChanges no longer leaves a pooled Business Entity with an invalid DatasetHandle

When the CannotFetchDataDuringSaveChangesException guard fired in one of the by-handle fetch variants of Consultingwerk.OERA.BusinessEntity, the FINALLY block restored the DatasetHandle property from a local variable that had never been assigned, wiping the property to UNKNOWN; the poisoned instance was returned to the pool and every following request on that ABL session failed with error 10068 or 3135 until the agent recycled. The FINALLY blocks of FetchData, FetchDataByKeyValues, FetchDataByKeyTable and FetchDataByStaticQuery now restore defensively and fall back to RestoreDatasetHandle when the saved handle is not valid, and the static ResetState and GetTopNavBuffers paths were hardened against an invalid dataset handle. A failed SaveChanges - including the framework's own guard exception - now leaves the pooled Business Entity fully usable. No changes required in customer code.

Business Entity constructor and InitializeDataAccessObject now raise strong-typed dataset exceptions

The two remaining plain Progress.Lang.AppError throws in Consultingwerk.OERA.BusinessEntity - the missing DatasetHandle guard in InitializeDataAccessObject and the invalid dataset reference guard in the constructor - now raise strong-typed exceptions from the Consultingwerk.OERA.Exceptions package (InvalidDatasetHandleException and InvalidDatasetReferenceException). Application code and unit tests can catch these two setup errors by type instead of matching on the message text. Since both classes inherit Progress.Lang.AppError through Consultingwerk.Exceptions.Exception, existing catch blocks keep working. No changes required in customer code.

REST record addresses can now use static data access queries via the new staticQuery annotation parameter

RestAddress annotations with type="record" can now be served through the static data access query infrastructure instead of a dynamic query, improving performance and single-record semantics. Opt in with the new annotation parameter staticQuery="true", which applies to the record GET as well as the record pre-fetch of PUT, PATCH and DELETE; collection addresses and addresses using a namedQuery are unaffected. Business Entities implement the new interface Consultingwerk.OERA.ISupportsStaticQueryRequests, whose GetStaticQueryRequest method is generated by the Business Entity Designer (AbstractStaticDataAccessQueryPlugin) for unique indexes flagged for static query generation; it returns the unknown value when no static query covers the requested table and field combination, in which case the RestEntitiesWebHandler falls back to the dynamic FetchData path. Regenerate the .annotations files and delete restresources-cache.json after changing an annotation; existing code continues to work unchanged when the parameter is not used.

Business Entity Designer now raises strong-typed exceptions instead of plain AppError

The plain Progress.Lang.AppError throws throughout the Business Entity Designer (Consultingwerk/BusinessEntityDesigner - generator, dataset controller, importer and plugin classes) have been replaced with a small set of strong-typed exception classes inheriting Consultingwerk.Exceptions.Exception, covering conditions such as a missing or invalid template and an unknown table or field. Code that extends the designer with custom plugins or generators can now catch these guard conditions by exception type instead of parsing message texts. Existing generic AppError catch blocks keep working, because Consultingwerk.Exceptions.Exception inherits Progress.Lang.AppError. No changes required in customer code.

SmartComponents adapters and controls now raise strong-typed exceptions instead of plain AppError

The plain Progress.Lang.AppError throws in the SmartComponents adapters, controls and support classes (Consultingwerk.SmartComponents), including SmartBusinessEntityAdapter, SmartDatasetAdapter, SmartViewerControl, SmartTempTableAdapter and SmartDatasetChildAdapter, have been replaced with strong-typed exception classes inheriting Consultingwerk.Exceptions.Exception, following the pattern established by InvalidDatasetHandleException and InvalidDatasetReferenceException. The new exception classes are located in an always-shipped namespace that respects the rule that Consultingwerk.SmartComponents must not depend on Consultingwerk.Windows.Framework or Consultingwerk.SmartFramework. Application code and unit tests can now catch these conditions by type; because Consultingwerk.Exceptions.Exception inherits Progress.Lang.AppError, existing generic AppError catch blocks keep working and no changes are required in customer code.

Root package base classes now raise strong-typed exceptions instead of plain AppError

The plain Progress.Lang.AppError throws in the root package base classes (Consultingwerk/Serializable.cls, LongcharInputStream.cls and QueryRowIdentifier.cls) have been replaced with strong-typed exception classes inheriting Consultingwerk.Exceptions.Exception. Developers can now catch invalid or unknown property access during serialization and the not-implemented guards by exception type rather than by inspecting the error message. Because Consultingwerk.Exceptions.Exception inherits Progress.Lang.AppError, existing generic AppError catch blocks continue to work unchanged. No changes required in customer code.

Util helper classes now raise strong-typed exceptions instead of plain AppError

The plain Progress.Lang.AppError throws in the helper classes under Consultingwerk/Util and Consultingwerk/Windows/Util (BufferHelper, WidgetHelper, StringHelper, QueryHelper, DatabaseHelper, FormHelper and others) have been replaced with strong-typed exception classes inheriting Consultingwerk.Exceptions.Exception. The new exception types live in Consultingwerk.Exceptions and remain free of .NET references so the helpers still compile on PASOE and Linux. Public helper method signatures are unchanged, and existing generic AppError catch blocks keep working. No changes required in customer code.

Remaining plain AppError throws in the OERA layer replaced with strong-typed exceptions

The remaining plain Progress.Lang.AppError throws in the OERA layer (Consultingwerk/OERA, OERA/support and Consultingwerk/Web2 - including DataAccess, ServiceInterface, TableModel, the query builders, the Swagger helpers and the web handlers) have been replaced with strong-typed exception classes in Consultingwerk.OERA.Exceptions, continuing the pattern established by InvalidDatasetHandleException and InvalidDatasetReferenceException. Callers and unit tests can now catch these conditions by exception type, and the new classes stay free of .NET references so the code keeps running server-side on PASOE. Existing generic AppError catch blocks continue to work. No changes required in customer code.

SmartFramework backend now raises strong-typed exceptions and dictionary-based messages instead of plain AppError

The plain Progress.Lang.AppError throws in the SmartFramework backend (Consultingwerk/SmartFramework - lock handling, authentication, authorization, attachments, menu and scheduler classes) have been replaced. User-facing message texts are now registered in the SmartFramework Message Dictionary and raised as SmartException ("SFR", <number>), while purely technical guards raise strong-typed classes inheriting Consultingwerk.Exceptions.Exception. This makes the conditions catchable by type and the messages translatable. The namespace remains server-side and free of .NET references, and existing generic AppError catch blocks continue to work. No changes required in customer code.

Windows GUI forms and controls now raise strong-typed exceptions instead of plain AppError

The plain Progress.Lang.AppError throws in the Windows GUI forms, dialogs and controls (Consultingwerk.Windows outside of Windows.Util, Consultingwerk.WindowIntegrationKit and Consultingwerk.Design.WinKit) have been replaced with strong-typed exception classes inheriting Consultingwerk.Exceptions.Exception, following the pattern established by InvalidDatasetHandleException and InvalidDatasetReferenceException. Recurring message shapes were grouped into shared exception types, so application code and unit tests can now catch these conditions by type rather than by message text. Because Consultingwerk.Exceptions.Exception inherits Progress.Lang.AppError, existing generic AppError catch blocks keep working and no changes are required in customer code.

Quick-Launch result providers are now registered against IQuickLaunchResultProvider using Service Keys

The seven core Quick-Launch result providers (MenuSearchProvider, WindowSwitchSearchProvider, RibbonButtonSearchProvider, ToolbarButtonSearchProvider, FolderPageSearchProvider, ObjectMasterSearchProvider and UserSearchProvider) are no longer registered against their own concrete class types. QuickLaunchBootstrapper:RegisterCoreProviders now registers them against the IQuickLaunchResultProvider interface using the keyed AddNewService overloads of FrameworkSettings:KeyedServiceContainer, with the Service Keys Menu, WindowSwitch, RibbonButton, ToolbarButton, FolderPage, ObjectMaster and User. Developers can enumerate all registered providers through GetServices (get-class (IQuickLaunchResultProvider)), optionally including the keys for diagnostics, and can replace or disable an individual provider by its key. The CustomerExplorer demo shows the intended usage sample: the new Consultingwerk.SmartComponentsDemo.CustomerExplorer.DemoSearchProviders enum together with the ServiceKey element in services.xml registers CustomerSearchProvider against the interface. Search dispatching is unchanged, so no changes are required in customer code.

Fixed: Bracket filter operators combined with an equals sign no longer silently drop the filter value

Query strings such as ?Country[EQ]=DE were parsed by the RestEntitiesWebHandler in a way that discarded the filter value, so the request answered HTTP 200 with a filter on a blank value instead of the expected rows. The handler now detects that the operator token terminates the query name while a value was supplied after the equals sign, and answers HTTP 400 Bad Request through BadRequestException. The working spellings ?Country[EQ]DE, ?Country=DE, ?CustNum>=42 and ?CustNum[>=]42 are unaffected. No changes required in customer code, unless an application relied on the previously silent behaviour.

New EnabledAlways design attribute keeps viewer controls enabled regardless of the viewer's Add or Update state

A new LOGICAL design attribute EnabledAlways has been added for MetaField, MetaButton, MetaCustomControl and MetaTreeView instances. When set to true it takes precedence over EnabledForAdd, EnabledForUpdate and EnabledOnCopy and registers the control with ControlEnabledEnum:Always in the GUI for .NET rendering (ViewerControlRenderer:RenderControl), while WebViewerRenderingHelper:FieldEnabledState emits enabledState = "always" for the Angular front end. Developers can now configure permanently enabled viewer controls declaratively in the repository instead of calling SetControlEnabled in viewer logic or implementing IAlwaysEnabledControl / IAlwaysEnabledContainerControl. TreeviewRendering now uses this generic evaluation and falls back to Always when the attribute is not present, so existing repositories keep their current behavior; all attribute reads are guarded with BufferHelper:HasField.

Quick Launch ribbon button (magnifying glass) added to the Customer Explorer and the reference MainMenuForm

A new Quick Launch ButtonTool with a magnifying glass icon has been added to the Launch ribbon group on the Start tab, rendered between the Launch Form and Windows List buttons. It was added to Consultingwerk.SmartComponentsDemo.CustomerExplorer.Main.CustomerExplorer and Consultingwerk.Windows.Framework.Reference.MainMenuForm, making the Quick Launch palette discoverable by mouse for users who are not aware of the Ctrl+Shift+P keyboard shortcut. The ToolClick handler resolves the optional Consultingwerk.SmartComponents.Interfaces.IGlobalShortcutService (registered by QuickLaunchBootstrapper:RegisterCoreProviders) and invokes it with the Ctrl+Shift+P key combination, so button and shortcut share a single code path. Developers can adopt the same pattern in their own ribbon forms; the button degrades gracefully in deployments that do not register the Quick Launch service.

Grid column reordering can now be disabled through the AllowColMoving design attribute in the GUI for .NET rendering

The AllowColMoving design attribute of the MetaGrid object type is now evaluated by the GUI for .NET rendering. DynamicBrowserRepository reads the attribute into the ttBrowserProperties temp-table (extended with a matching field) and DynamicBrowserRenderer maps it to the UltraGrid DisplayLayout:Override:AllowColMoving property, following the existing AllowGroupBy pattern. When the attribute is set to false, users can no longer reorder grid columns by dragging the column headers. Web rendering is not affected by this change.

Business Entity Designer can now import an existing XML document and derive temp-tables and fields from it

The Business Entity Designer offers a new import option that reads an XML document from disk and derives the temp-tables and fields of a Business Entity from the data structure of that document. Repeating XML elements become (child) temp-tables including the parent/child data-relations, while simple element values and XML attributes become fields whose ABL data types (character, integer, decimal, date, datetime-tz, logical) are inferred from the actual values across all occurrences. The derived tables and fields follow the Business Entity Designer naming conventions (e-prefixed table names, PascalCase field names), so the result can be used directly for generating a Business Entity. This complements the schema-based import from database tables for XML payloads without an available schema, such as bank statement (camt.053) or interface files; the derivation is covered by unit tests.

New EditAsTextbox mode for lookups: lookup behaves as a plain text field while a record is added, copied or modified

A new EditAsTextbox (LOGICAL) design attribute has been added to lookup instances. While no record is being edited, the lookup behaves as a regular lookup and continues to raise value changed, Enter key and other events, so it can be used as an always-enabled filter control on a maintenance screen (in combination with the viewer repository rendering support for ControlEnabledEnum:Always). While a record is being added, copied or modified, the lookup switches its appearance and behaviour to a simple text field: the built-in ValueChanged and Leave handling that fetches the referenced record from the backend is suppressed and the editor buttons are no longer available. Developers enable the mode by setting the EditAsTextbox design attribute on the lookup instance; the Angular front end provides the corresponding behaviour.

Fixed: ValueListHelper now boxes the flag/dummy entry using the data type of the key field

Consultingwerk.Util.ValueListHelper inserted the optional flag/dummy entry (pcFlagValue/pcFlagText) into the ValueList as a CHARACTER value, while all regular entries were boxed using the actual data type of the key field. For a value list keyed by a non-CHARACTER field such as DECIMAL this produced mixed value types, so UNBOX-ing the selected value of the flag entry failed with a mismatched parameters runtime error (error 2570). The flag entry is now boxed to the ABL data type of the key field using DataTypeHelper:ToSystemObject, consistently in all affected overloads of FromTempTable, FromTempTableWithSort, FromTempTableAndImageProviderWithSort and the FromBusinessEntity methods that funnel into them. No changes required in customer code; existing workarounds that special-cased the flag entry can be removed.

PASOE instances for different OpenEdge releases can now run in parallel, with environment tokens in AppServer connection sources

Each PASOE instance in the workspace now uses its own set of HTTP, HTTPS, AJP, shutdown and healthcheck ports (documented in PASOE-PORTS.md), and scl-workspace-config.cmd provides the new settings SCL-PASOE-HTTP and SCL-PASOE-HTTPS per OpenEdge release; SCL-PASOE-PORT remains as a deprecated alias. The environment token syntax ${env.NAME}, ${env.NAME:default} and ${?env.NAME} was extracted into the reusable helper class Consultingwerk.Framework.EnvironmentTokenResolver and is now applied to the AppServer connection profiles in appsrvtt.d (resolved at connect time in as-utils.w), to AppServer URLs passed as -param AppServer=..., and to the port specific values of .applicationsettings and .restapplicationsettings. This makes AppServer connection definitions workspace neutral, so the same file works in every checkout. The MCP servers are launched through wrapper batch files in Scripts/ that call scl-workspace-config.cmd first, so each session connects to the PASOE instance of its own checkout.

Business Entity Designer: fields can now be copied and pasted between temp-tables

A field selected in a temp-table shape on the Business Entity Designer canvas can now be copied with the new context menu item Copy Field (or Ctrl+C) and inserted into another or the same temp-table with Paste Field (or Ctrl+V). A dialog offers to paste the field as a database field when its database table is already a source table of the target temp-table, as a database field with that database table added as an additional source table, or as a calculated field without source information. All field attributes and custom field properties are copied along, the field is appended at the end of the field list, and name conflicts are resolved with the existing unique field name prompt. The existing Copy Field Names menu item is unchanged, and Ctrl+C / Ctrl+V keep their normal text clipboard behaviour inside the docked editors.

ProparseAbl parity test suite added for the upstream sonar-openedge Proparse test resources

The ABL test programs of the upstream sonar-openedge Proparse project are now vendored into the UnitTests project as fixtures excluded from compilation, keeping the upstream folder structure so the corpus can be refreshed by diffing against upstream. A new SmartUnit test runner parses every fixture with both the pure-ABL ProparseAblApi and the reference ProparseDotNetApi and compares the results per file on node sequence, tree shape and symbol model level using ProparseParityComparer. The suite is registered in unittests.xml, so Jenkins produces a per-file result trend, and it can be run locally through sclant. This is an internal quality measure; no changes are required in customer code.

Grid JSON rendering now emits hidden and includeInChooser per column and can offer data source fields in the column chooser

The rendered grid layout JSON produced by GridWebRendering now carries hidden: true for columns whose HIDDEN attribute is set and includeInChooser: false for columns marked with ExcludeFromColumnChooser, so the web grid can distinguish columns hidden from the grid from columns excluded from the column chooser. In addition, the new grid attribute DataSourceFieldsInColumnChooser appends every field of the design-time data source that is not part of the grid design as an additional hidden but choosable column, which avoids putting more than a hundred columns into the grid design just to make them reachable. Grids whose columns carry none of these attributes render exactly the same JSON as before, and field security keeps removing hidden fields from the layout entirely. The new attributes have to be registered in the repository meta data before they can be used.

Fixed: ProparseAbl now nests the USING field clause of a FIND record phrase under the RECORD_NAME node

The pure-ABL Proparse implementation now parses the USING field (AND field) option of a FIND or FOR EACH record phrase as part of the record phrase, nesting the USING node and its Field_ref children under the RECORD_NAME node, matching the reference parser. No changes required in customer code, unless custom code navigates the syntax tree and relied on the previous, non-conforming node layout.

Business Entity lookups are now data type aware and support INTEGER, INT64 and DECIMAL key fields

SmartBusinessEntityLookup and the repository lookup rendering for GUI for .NET and Angular now take the data type of the lookup key field into account instead of always rendering a plain text editor. Numeric key fields (INTEGER, INT64, DECIMAL) are rendered with numeric alignment, an input mask derived from the field format and typed value handling, and the generated lookup queries use typed literals instead of quoted string values. The key field data type is derived automatically from the schema of the lookup Business Entity, so existing lookups benefit without repository changes; the NumericType attribute remains available as an explicit override and now also supports Int64.

Fixed: The Web Sessions screen now opens without the GDI+ "Parameter is not valid." error and renders its toolbar correctly

Opening the Web Sessions screen (SmartContextStoreForm) no longer raises a GDI+ "Parameter is not valid." error, and the toolbar area with the Lock Selected Session and Lock All User Sessions buttons is painted correctly instead of showing a red X. The session grid now retrieves and displays data as expected. No changes required in customer code.