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_CONNECTIONtook 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 andDataProviderF4Valuedoes 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.