Table of Contents

Migrating from the command API client

The BiExcellence.OpenBi.Api packages (IOpenBiSession and the BiExcellence.OpenBi.Api.Commands.* extension methods) talk to the server's legacy command API. This client talks to its REST API instead. The server still serves the command API, so the two can be used side by side while an application moves over.

The session becomes a client

Command API client REST client
new OpenBiSession(new OpenBiConfiguration(Protocol.HTTP, "host", 9093, "app")) new OpenBiApiClient(new Uri("http://host:9093/openbi/api/"))
IOpenBiSession IOpenBiApiClient
session.OpenBiLoginAsync(user, password) client.LoginAsync(user, password) - see Authentication
session.GetSessionInformationAsync() client.GetCurrentUserInfoAsync()
session.PingAsync() client.GetHealthLiveAsync()
using BiExcellence.OpenBi.Api.Commands.<Area>; using BiExcellence.OpenBi.Api.<Area>;
IFilter / Filter on a list command OpenBiListRequest - see Lists
OpenBiServerErrorException OpenBiApiException - see Errors
session.OnRequest / OnResponse / OnError A DelegatingHandler in the HttpClient pipeline

The session was a server-side session with a handle. The REST client is stateless apart from its bearer token: there is nothing to open or close, and one client can be shared across threads.

Custom commands

session.CreateRequest("CUSTOM_COMMAND") has no REST equivalent. A command handler that a plugin adds to the server is reached through the command API only, so an application that calls one keeps using the command API client for that call.

DataProviders: the type names

The legacy client was IOpenBiSession extension methods over the Command API. The concepts carry over - it is the same engine - but the names do not.

Legacy REST client
IDataProviderView DataProviderView (a class; there is no interface)
view.Session view.Client
view.DataProviderDefinition view.Definition (or view.Dimensions / .KeyFigures / .Variables)
IDataProviderDefinition, DataProviderDefinition DataProviderDefinition
IDimension, Dimension DataProviderDimension
IKeyFigure, KeyFigure DataProviderKeyFigure
IVariable, Variable DataProviderVariable
ICondition, Condition DataProviderCondition
IFilter, Filter DataProviderFilter
IDrillState, DrillState DataProviderDrillState; a drill path is a List<DataProviderDrillState>
IAlertLevel DataProviderAlertLevel
ISortTuple DataProviderSortTuple
dimension.DataType, keyFigure.DataType .Type (a DbType)
variable.DataType .DataType (a DbType?)
dimension.Attribute .CaptionAttribute (the attribute's id, not the attribute)
dimension.Hierarchy .HierarchyName + .HierarchyActive; .Hierarchies lists what is on offer
dimension.DateInputFormat / DateOutputFormat .InputFormat / .OutputFormat
dimension.IsKeyFigureDimension .ContainsKeyFigures
keyFigure.IsHidden, dimension.IsHidden .Visible (bool?; absent means visible, so the sense is inverted)
variable.Entrytp / Vartyp / Iobjnm .EntryType / .Type / .DimensionId
DimensionAxis DataProviderAxis
DimensionSumState DataProviderSumState
DimensionSortType DataProviderSortType
InfoObjectSortMode DataProviderSortMode
InfoObjectDataType System.Data.DbType (String, Double, Date, Boolean; Integer is Int64)
KeyFigureAggregation DataProviderAggregation
KeyFigureCalculationTime DataProviderCalculationTime
VariableType / VariableSelection / VariableEntryType DataProviderVariableType / -Selection / -EntryType
FilterOperator / FilterSign DataProviderFilterOperator / DataProviderFilterSign
DrillStateValue.Expanded DataProviderDrillStates.Expanded (the wire's own "E", "C", "L")
AffectedDataProviderMode.FiltersAndDimensions / .Filters / .Dimensions / .None DataProviderStateEffect.Both / .Filter / .DrillDown / .None
IAffectedDataProvider, AffectedDataProvider AffectedDataProvider (Mode is Effect)
IExecuteDefinition DataProviderExecuteResult
.ColumnCount .ColCount (RowCount keeps its name)
.HasDataProviderDefinitionChanged .DefinitionChanged
.HasGeoLocations, .SupportsMasterData .ViewSupportsMap
IGridData (an IList<IGridCell>) DataProviderGridData, whose cells are .Cells
IGridCell and its five interfaces DataProviderGridCell; .Content says what the cell is
Assert.IsAssignableFrom<IValueGridCell>(c).Data c.Value (a double?, parsed invariantly from .Data)
cell.Decimals / .Scaling .NumPrec / .NumScale
ITuple DataProviderAxisData
IF4Values (an IList<IF4Value>) DataProviderF4Values, whose values are .Values
IChartData.Points / .Categories / .Groups DataProviderChartData.Data / .Categories / .Groups
IChartPoint.Data (a double) DataProviderChartValue.Value (a double?, parsed invariantly from .Data)
IChartPoint.AlertLevelId (0 for none) DataProviderChartValue.AlertLevel (null for none)
IValueGridCell.AlertLevelId (0 for none) DataProviderGridCell.AlertLevel (null for none)
IExportDocument OpenBiApiFile (MediaType, and the bytes as a stream)
IDataComment, GetDataCommentsAsync DataProviderDocument, GetTextsAsync
IDataComment.Content / .Attributes .ContentAscii / .Attributes (values are JsonElement)
view.CreateDataCommentAsync(...) view.CreateCommentAsync(...), same two forms
view.DeleteDataCommentAsync(id) view.DeleteCommentAsync(id)
IDataProviderNode, IDataProvider DataProviderNode
IUsedConnections, IConnection OpenDataProviderResult and its UsedConnections
session.ValidateConnectionAsync(template) client.ValidateConnectionTemplateAsync(templateId, request)
session.OpenDataProviderAsync(...) client.OpenDataProviderAsync(name, request)
usedConnections.GetDataProviderViewAsync() client.GetDataProviderViewAsync(name)
view.SaveViewAsync(contentId) view.SaveAsync(id) - returns the view, whose .Id is the content element id
view.GetExportDocumentAsync(format) view.ExportAsync(DataProviderExportFormat.Xlsx)
session.GetDataProvidersAsync(connection) client.GetDataProviderNodesAsync(name)
DataProviderTypes.SAP_BW (constants) the type strings themselves - the client has no constants for them

Three things have no equivalent, by design:

  • VisualMode / DataVisualType. Actual-versus-plan was a mode on every execute; the REST API does not carry it.
  • An ad hoc connection template. VALIDATE_CONNECTION took a whole template as its body, stored or not. The REST route validates one by id, so a caller that built a template in memory has to store it first (POST connectiontemplates) - or use one of the built-in ids (OPENBI, MASTER, ENTITY, CORE).
  • IF4Value.Iobjnm. The value help echoed back the characteristic the caller had just asked about. The REST route is addressed by that characteristic (?dimension= / ?variable=), so the caller already holds it and DataProviderF4Value does not carry it. Niobjnm - the other characteristic a hierarchy node belongs to - is still there, because nothing else says it.

The variables a legacy caller sent along with a value help request are not lost either: they go in the body of POST dataproviders/{id}/f4values, which client.GetDataProviderF4ValuesAsync(name, request) and view.GetF4ValuesAsync(request) call. The query-string form narrows by the filters the dataprovider already holds, which is what a caller reading its own session wants; send a context where the answers in hand are not the ones it was executed with. Variables = [] asks for the values without any answers at all.

One thing only looks missing: an exception on a chart point. The chart puts the two-digit level in color where it was asked for exceptions, exactly as the legacy API did, and DataProviderChartValue.AlertLevel reads it - null rather than 0 where there is none, matching the grid.