Uniphar.Sap.Odata.Client
4.0.1
See the version list below for details.
dotnet add package Uniphar.Sap.Odata.Client --version 4.0.1
NuGet\Install-Package Uniphar.Sap.Odata.Client -Version 4.0.1
<PackageReference Include="Uniphar.Sap.Odata.Client" Version="4.0.1" />
<PackageVersion Include="Uniphar.Sap.Odata.Client" Version="4.0.1" />
<PackageReference Include="Uniphar.Sap.Odata.Client" />
paket add Uniphar.Sap.Odata.Client --version 4.0.1
#r "nuget: Uniphar.Sap.Odata.Client, 4.0.1"
#addin nuget:?package=Uniphar.Sap.Odata.Client&version=4.0.1
#tool nuget:?package=Uniphar.Sap.Odata.Client&version=4.0.1
sap-odata-client
NuGet package repository for Sap OData Client connection
Purpose
This library is for making calls to SAP (running in AZ). Calls to SAP require a base url. Full path will be decorated with the namespace of the service we call.
Calls to the SAP instance requires authentication with Basic auth
- (username
and password
). These are stored in a secret storage and you do not need to define these. The secret storage can be AZ Keyvault
, AWS Secrets Manager
or others. Any token
expiry is automatically handled by the SAP client and is not something to be concerned with either.
Custom Events
The library also publishes some custom telemetry events. This is because there has been several issues with the SAP Rise environments. We publish the following events
Event | Description | Remarks |
---|---|---|
SapTokenExpiredEvent | When x-csrf-token has expired, and we get a 403 back when calling the SAP Rise instance |
|
SapTokenUnauthorizedFetchEvent | When requesting a new x-csrf-token SAP returns a 401 instead of the expected 403 |
The system will throw an UnauthorizedAccessException |
SapTokenRefreshedFetchEvent | When requesting a new x-csrf-token , and SAP returns anything but 401 , we notify it was part of the Response headers |
|
SapTokenNotFoundEvent | When requesting a new x-csrf-token , and SAP returns anything but 401 . However, response headers do not contain x-csrf-token |
Setup your project to use SapClient package
When using this NuGet package you need to setup a few things in your project
SapClientOptions
Property | IsRequired | Description |
---|---|---|
SapRiseUserName | True | The SAP user account name |
SapRisePassword | True | The SAP user account password |
FetchTokenStatusCodeTriggers | False | The set of HttpStatus codes that should trigger renewal of sap token fetching. Default is 401. |
NOTE: :
FetchTokenStatusCodeTriggers
is a list of HttpCodes we test against to trigger fetching a new token. We predefine the status code to check for asForbidden (403)
. If the issue we encountered before (returning401
instead of403
) starts again, you need to update the appsettings.json to handle both status codes. You should do that in the project that consumes this NuGet package.Significant changes with version 2.0.2
UseHttpClientHandler
andPooledConnectionLifetime
have been retired with version 2.0.2, as we now use short-living http client instances created by HttpClientFactory. These are no longer part ofSapClientOptions
either.
Program.cs
Add the following to Program.cs
- Add this to bind the above configuration section to class
SapClientOptions
. That will ensure we can DI it into the SapClient class.
builder.Services.Configure<SapClientOptions>(
builder.Configuration.GetSection(nameof(SapClientOptions)));
- Register a singleton instance of HttpClient, as SapClient makes calls to SAP RISE over HTTP.
// If we need to use NullProxy
if (bool.Parse(builder.Configuration["InstanceConfig:EnableNullProxy"]!))
{
builder.Services.AddTransient<ISapClient, NullSapClient>();
}
else
{
// Register SAP client
builder.Services.AddTransient<ISapClient, SapClient>();
// Register HttpClient
builder.Services.AddHttpClient(nameof(SapClient), client =>
{
client.BaseAddress = new Uri(builder.Configuration["BaseUrl"]!);
client.Timeout = TimeSpan.Parse(builder.Configuration["Timeout"]!);
});
}
NOTE: : In the example above we have registered a named client as we intend to use same configuration for all delegated clients when making request to SAP Rise.
Using SapClient library
We have a couple of predefined (and custom) JsonSerialisers
we need to use when calling SAP. This is handled by class SapJsonSerializer
. It exposes a static method:
public static JsonSerializerOptions GetJsonSerializerOptions()
{
// preliminary code logic
jsonSerializerOptions.Converters.Add(new SapDateTimeConverter());
jsonSerializerOptions.Converters.Add(new SapDateTimeOffsetConverter());
jsonSerializerOptions.Converters.Add(new SapDecimalConverter());
return jsonSerializerOptions;
}
The SAP client package exposes two methods
Task<ContentResult> GetAsync<T>(string path, CancellationToken cancellationToken)
Task<ContentResult> PostAsync<T>(string path, T message, CancellationToken cancellationToken)
Both methods return a ContentResult
, which means we can handle based on the Http status code in the response.
Example usage:
public async Task<ActionResult<SalesOrderResponse>> CreateToDoList([FromBody] CreateToDoList createToDoList, CancellationToken cancellationToken)
{
// Call SAP Client to get Serializer Options
var serializerOptions = SapJsonSerializer.GetJsonSerializerOptions();
// Make call to SAP Client POST method
var createdTodoListContentResult = await _sapClient.PostAsync("TO_DO_LIST_API", createToDoList.MapToSapToDoListRequest(), cancellationToken);
switch(createdTodoListContentResult.StatusCode)
{
case 201:
var createdSapTodoListResult = JsonSerializer.Deserialize<OData<ToDoList>>(createdTodoListContentResult.Content!, serializerOptions);
// Make call to SAP Client GET method
var sapToDoListWithItems = await _sapClient.GetAsync<OData<ToDoList>>(
$"TO_DO_LIST_API/TO_DO_LIST_ITEM('{createdSapTodoListResult!.Data!.Id}')?$expand=to_Item", cancellationToken);
var sapToDoList = JsonSerializer.Deserialize<OData<ToDoList>>(sapToDoListWithItems.Content!, serializerOptions);
var newSapToDoList = sapToDoList!.Data!.MapToSapToDoListResponse();
return CreatedAtAction(nameof(CreateToDoList), new { id = newSalesOrder.Id }, newSalesOrder);
case 400:
var sapErrorResponse = JsonSerializer.Deserialize<SapErrorResponse>(createdTodoListContentResult.Content!, options);
return BadRequest(sapErrorResponse!.MapToProblemDetails());
default:
return new StatusCodeResult((int)createdTodoListContentResult.StatusCode!);
}
}
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.ApplicationInsights (>= 2.22.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated | |
---|---|---|---|
7.0.0 | 1,834 | 2/19/2025 | |
6.0.0 | 382 | 1/28/2025 | |
5.0.3 | 264 | 12/10/2024 | |
5.0.2 | 110 | 12/10/2024 | |
5.0.1 | 157 | 12/2/2024 | |
5.0.0 | 145 | 11/26/2024 | |
4.1.0 | 185 | 11/14/2024 | |
4.0.3 | 151 | 11/1/2024 | |
4.0.2 | 121 | 10/31/2024 | |
4.0.1 | 116 | 10/31/2024 | |
4.0.0 | 121 | 10/30/2024 | |
3.1.0 | 121 | 10/29/2024 | |
3.0.0 | 121 | 10/25/2024 | |
2.0.4 | 398 | 10/1/2024 | |
2.0.3 | 156 | 9/25/2024 | |
2.0.2 | 149 | 9/24/2024 | |
2.0.1 | 509 | 5/16/2024 | |
2.0.0 | 134 | 5/14/2024 | |
1.0.6 | 616 | 4/8/2024 | |
1.0.5 | 133 | 4/5/2024 | |
1.0.4 | 190 | 4/2/2024 | |
1.0.3 | 150 | 4/2/2024 | |
1.0.2 | 133 | 3/29/2024 | |
1.0.0 | 870 | 12/15/2023 | |
0.4.1 | 159 | 12/15/2023 | |
0.3.0 | 167 | 12/14/2023 | |
0.1.1 | 141 | 12/14/2023 | |
0.1.0 | 151 | 12/14/2023 |