diff --git a/Client/Com/Cumulocity/Client/Api/AttachmentsApi.cs b/Client/Com/Cumulocity/Client/Api/AttachmentsApi.cs index 68aa77e..57445c0 100644 --- a/Client/Com/Cumulocity/Client/Api/AttachmentsApi.cs +++ b/Client/Com/Cumulocity/Client/Api/AttachmentsApi.cs @@ -22,7 +22,7 @@ namespace Client.Com.Cumulocity.Client.Api; /// -/// It is possible to store, retrieve and delete binaries for events. Each event can have one binary attached.
+/// It is possible to store, retrieve and delete binaries for events. Each event can have only one binary attached.
///
/// public sealed class AttachmentsApi : IAttachmentsApi @@ -63,7 +63,7 @@ public AttachmentsApi(HttpClient httpClient) RequestUri = new Uri(uriBuilder.ToString()) }; request.Headers.TryAddWithoutValidation("Content-Type", "text/plain"); - request.Headers.TryAddWithoutValidation("Accept", "application/vnd.com.nsn.cumulocity.error+json, application/vnd.com.nsn.cumulocity.event+json"); + request.Headers.TryAddWithoutValidation("Accept", "application/vnd.com.nsn.cumulocity.error+json, application/json"); using var response = await _httpClient.SendAsync(request: request, cancellationToken: cToken).ConfigureAwait(false); await response.EnsureSuccessStatusCodeWithContentInfo().ConfigureAwait(false); await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); @@ -82,7 +82,7 @@ public AttachmentsApi(HttpClient httpClient) RequestUri = new Uri(uriBuilder.ToString()) }; request.Headers.TryAddWithoutValidation("Content-Type", "text/plain"); - request.Headers.TryAddWithoutValidation("Accept", "application/vnd.com.nsn.cumulocity.error+json, application/vnd.com.nsn.cumulocity.event+json"); + request.Headers.TryAddWithoutValidation("Accept", "application/vnd.com.nsn.cumulocity.error+json, application/json"); using var response = await _httpClient.SendAsync(request: request, cancellationToken: cToken).ConfigureAwait(false); await response.EnsureSuccessStatusCodeWithContentInfo().ConfigureAwait(false); await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); @@ -108,7 +108,7 @@ public AttachmentsApi(HttpClient httpClient) RequestUri = new Uri(uriBuilder.ToString()) }; request.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data"); - request.Headers.TryAddWithoutValidation("Accept", "application/vnd.com.nsn.cumulocity.error+json, application/vnd.com.nsn.cumulocity.event+json"); + request.Headers.TryAddWithoutValidation("Accept", "application/vnd.com.nsn.cumulocity.error+json, application/json"); using var response = await _httpClient.SendAsync(request: request, cancellationToken: cToken).ConfigureAwait(false); await response.EnsureSuccessStatusCodeWithContentInfo().ConfigureAwait(false); await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); diff --git a/Client/Com/Cumulocity/Client/Api/BinariesApi.cs b/Client/Com/Cumulocity/Client/Api/BinariesApi.cs index 913d87b..0b0f03f 100644 --- a/Client/Com/Cumulocity/Client/Api/BinariesApi.cs +++ b/Client/Com/Cumulocity/Client/Api/BinariesApi.cs @@ -23,7 +23,7 @@ namespace Client.Com.Cumulocity.Client.Api; /// /// Managed objects can perform operations to store, retrieve and delete binaries. One binary can store only one file. Together with the binary, a managed object is created which acts as a metadata information for the binary.
-/// ⓘ Info: The Accept header should be provided in all POST/PUT requests, otherwise an empty response body will be returned.
+/// ⓘ Info: Supports only HTTP 1.1 clients.ⓘ Info: The Accept header should be provided in all POST/PUT requests, otherwise an empty response body will be returned.
///
/// public sealed class BinariesApi : IBinariesApi diff --git a/Client/Com/Cumulocity/Client/Api/CurrentUserApi.cs b/Client/Com/Cumulocity/Client/Api/CurrentUserApi.cs index e816f28..e3f4121 100644 --- a/Client/Com/Cumulocity/Client/Api/CurrentUserApi.cs +++ b/Client/Com/Cumulocity/Client/Api/CurrentUserApi.cs @@ -62,7 +62,6 @@ public CurrentUserApi(HttpClient httpClient) jsonNode?.RemoveFromNode("id"); jsonNode?.RemoveFromNode("lastPasswordChange"); jsonNode?.RemoveFromNode("twoFactorAuthenticationEnabled"); - jsonNode?.RemoveFromNode("devicePermissions"); const string resourcePath = "/user/currentUser"; var uriBuilder = new UriBuilder(new Uri(_httpClient.BaseAddress ?? new Uri(resourcePath), resourcePath)); using var request = new HttpRequestMessage diff --git a/Client/Com/Cumulocity/Client/Api/DevicePermissionsApi.cs b/Client/Com/Cumulocity/Client/Api/DevicePermissionsApi.cs index ef9adce..d553d5d 100644 --- a/Client/Com/Cumulocity/Client/Api/DevicePermissionsApi.cs +++ b/Client/Com/Cumulocity/Client/Api/DevicePermissionsApi.cs @@ -64,7 +64,7 @@ public DevicePermissionsApi(HttpClient httpClient) } /// - public async Task?> GetDevicePermissionAssignments(string id, CancellationToken cToken = default) where TCustomProperties : CustomProperties + public async Task?> GetDevicePermissionAssignments(string id, CancellationToken cToken = default) where TCustomProperties : CustomProperties { string resourcePath = $"/user/devicePermissions/{HttpUtility.UrlEncode(id.GetStringValue())}"; var uriBuilder = new UriBuilder(new Uri(_httpClient.BaseAddress ?? new Uri(resourcePath), resourcePath)); @@ -77,13 +77,13 @@ public DevicePermissionsApi(HttpClient httpClient) using var response = await _httpClient.SendAsync(request: request, cancellationToken: cToken).ConfigureAwait(false); await response.EnsureSuccessStatusCodeWithContentInfo().ConfigureAwait(false); await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); - return await JsonSerializerWrapper.DeserializeAsync?>(responseStream, cancellationToken: cToken).ConfigureAwait(false);; + return await JsonSerializerWrapper.DeserializeAsync?>(responseStream, cancellationToken: cToken).ConfigureAwait(false);; } /// - public async Task UpdateDevicePermissionAssignments(DevicePermissions body, string id, CancellationToken cToken = default) where TCustomProperties : CustomProperties + public async Task UpdateDevicePermissionAssignments(UpdatedDevicePermissions body, string id, CancellationToken cToken = default) { - var jsonNode = body.ToJsonNode>(); + var jsonNode = body.ToJsonNode(); string resourcePath = $"/user/devicePermissions/{HttpUtility.UrlEncode(id.GetStringValue())}"; var uriBuilder = new UriBuilder(new Uri(_httpClient.BaseAddress ?? new Uri(resourcePath), resourcePath)); using var request = new HttpRequestMessage diff --git a/Client/Com/Cumulocity/Client/Api/IAlarmsApi.cs b/Client/Com/Cumulocity/Client/Api/IAlarmsApi.cs index d1eab9f..7be6e1e 100644 --- a/Client/Com/Cumulocity/Client/Api/IAlarmsApi.cs +++ b/Client/Com/Cumulocity/Client/Api/IAlarmsApi.cs @@ -178,7 +178,7 @@ public interface IAlarmsApi /// /// Remove alarm collections
/// Remove alarm collections specified by query parameters.
- /// ⚠️ Important: DELETE requires at least one of the following parameters: source, dateFrom, dateTo, createdFrom, createdTo.Also note that DELETE requests are not synchronous. The response could be returned before the delete request has been completed.
+ /// ⚠️ Important: Note that it is possible to call this endpoint without providing any parameter - it will result in deleting all alarms and it is not recommended.Also note that DELETE requests are not synchronous. The response could be returned before the delete request has been completed.
/// ///
Required roles
/// ROLE_ALARM_ADMIN diff --git a/Client/Com/Cumulocity/Client/Api/IAttachmentsApi.cs b/Client/Com/Cumulocity/Client/Api/IAttachmentsApi.cs index 993864e..43757ea 100644 --- a/Client/Com/Cumulocity/Client/Api/IAttachmentsApi.cs +++ b/Client/Com/Cumulocity/Client/Api/IAttachmentsApi.cs @@ -15,7 +15,7 @@ namespace Client.Com.Cumulocity.Client.Api; /// -/// It is possible to store, retrieve and delete binaries for events. Each event can have one binary attached.
+/// It is possible to store, retrieve and delete binaries for events. Each event can have only one binary attached.
///
/// public interface IAttachmentsApi @@ -83,9 +83,9 @@ public interface IAttachmentsApi /// /// Attach a file to a specific event
- /// Upload a file (binary) as an attachment of a specific event by a given ID.
- /// The size of the attachment is configurable, and the default size is 50 MiB. The default chunk size is 5MiB.
- /// After the file has been uploaded, the corresponding event will contain the fragment c8y_IsBinary similar to:
+ /// Upload a file (binary) as an attachment of a specific event by a given ID.The size of the attachment is configurable, and the default size is 50 MiB. The default chunk size is 5MiB.
+ /// ⓘ Info: If there is a binary already attached to the event, the POST request results in a 409 error.
+ /// When the file has been uploaded, the corresponding event contains the fragment c8y_IsBinary similar to:
/// - /// When using multipart/form-data each value is sent as a block of data (body part), with a user agent-defined delimiter (boundary) separating each part. The keys are given in the Content-Disposition header of each part.
+ /// There are two request body schemas you can use for your POST requests.text/plain is preselected (see below).If you set it to multipart/form-data each value is sent as a block of data (body part), with a user agent-defined delimiter (boundary) separating each part.The keys are given in the Content-Disposition header of each part.
/// @@ -145,9 +145,9 @@ public interface IAttachmentsApi /// /// Attach a file to a specific event
- /// Upload a file (binary) as an attachment of a specific event by a given ID.
- /// The size of the attachment is configurable, and the default size is 50 MiB. The default chunk size is 5MiB.
- /// After the file has been uploaded, the corresponding event will contain the fragment c8y_IsBinary similar to:
+ /// Upload a file (binary) as an attachment of a specific event by a given ID.The size of the attachment is configurable, and the default size is 50 MiB. The default chunk size is 5MiB.
+ /// ⓘ Info: If there is a binary already attached to the event, the POST request results in a 409 error.
+ /// When the file has been uploaded, the corresponding event contains the fragment c8y_IsBinary similar to:
/// - /// When using multipart/form-data each value is sent as a block of data (body part), with a user agent-defined delimiter (boundary) separating each part. The keys are given in the Content-Disposition header of each part.
+ /// There are two request body schemas you can use for your POST requests.text/plain is preselected (see below).If you set it to multipart/form-data each value is sent as a block of data (body part), with a user agent-defined delimiter (boundary) separating each part.The keys are given in the Content-Disposition header of each part.
/// diff --git a/Client/Com/Cumulocity/Client/Api/IBinariesApi.cs b/Client/Com/Cumulocity/Client/Api/IBinariesApi.cs index 2698cf1..51c48c8 100644 --- a/Client/Com/Cumulocity/Client/Api/IBinariesApi.cs +++ b/Client/Com/Cumulocity/Client/Api/IBinariesApi.cs @@ -16,7 +16,7 @@ namespace Client.Com.Cumulocity.Client.Api; /// /// Managed objects can perform operations to store, retrieve and delete binaries. One binary can store only one file. Together with the binary, a managed object is created which acts as a metadata information for the binary.
-/// ⓘ Info: The Accept header should be provided in all POST/PUT requests, otherwise an empty response body will be returned.
+/// ⓘ Info: Supports only HTTP 1.1 clients.ⓘ Info: The Accept header should be provided in all POST/PUT requests, otherwise an empty response body will be returned.
///
/// public interface IBinariesApi diff --git a/Client/Com/Cumulocity/Client/Api/IDevicePermissionsApi.cs b/Client/Com/Cumulocity/Client/Api/IDevicePermissionsApi.cs index 0e8f5a8..5e11bfb 100644 --- a/Client/Com/Cumulocity/Client/Api/IDevicePermissionsApi.cs +++ b/Client/Com/Cumulocity/Client/Api/IDevicePermissionsApi.cs @@ -77,7 +77,7 @@ public interface IDevicePermissionsApi /// Unique identifier of the managed object.
/// Propagates notification that operations should be canceled.
/// - Task?> GetDevicePermissionAssignments(string id, CancellationToken cToken = default) where TCustomProperties : CustomProperties; + Task?> GetDevicePermissionAssignments(string id, CancellationToken cToken = default) where TCustomProperties : CustomProperties; /// /// Updates the device permissions assignments
@@ -107,5 +107,5 @@ public interface IDevicePermissionsApi /// Unique identifier of the managed object.
/// Propagates notification that operations should be canceled.
/// - Task UpdateDevicePermissionAssignments(DevicePermissions body, string id, CancellationToken cToken = default) where TCustomProperties : CustomProperties; + Task UpdateDevicePermissionAssignments(UpdatedDevicePermissions body, string id, CancellationToken cToken = default) ; } diff --git a/Client/Com/Cumulocity/Client/Api/IEventsApi.cs b/Client/Com/Cumulocity/Client/Api/IEventsApi.cs index 6bf44d1..2c49510 100644 --- a/Client/Com/Cumulocity/Client/Api/IEventsApi.cs +++ b/Client/Com/Cumulocity/Client/Api/IEventsApi.cs @@ -121,7 +121,7 @@ public interface IEventsApi /// Remove event collections
/// Remove event collections specified by query parameters.
/// DELETE requests are not synchronous. The response could be returned before the delete request has been completed. This may happen especially when the deleted event has a lot of associated data. After sending the request, the platform starts deleting the associated data in an asynchronous way. Finally, the requested event is deleted after all associated data has been deleted.
- /// ⚠️ Important: DELETE requires at least one of the following parameters: source, dateFrom, dateTo, createdFrom, createdTo.
+ /// ⚠️ Important: Note that it is possible to call this endpoint without providing any parameter - it will result in deleting all events and it is not recommended.
/// ///
Required roles
/// ROLE_EVENT_ADMIN diff --git a/Client/Com/Cumulocity/Client/Api/IManagedObjectsApi.cs b/Client/Com/Cumulocity/Client/Api/IManagedObjectsApi.cs index 92e408c..9e4bbc4 100644 --- a/Client/Com/Cumulocity/Client/Api/IManagedObjectsApi.cs +++ b/Client/Com/Cumulocity/Client/Api/IManagedObjectsApi.cs @@ -125,38 +125,6 @@ public interface IManagedObjectsApi /// Task CreateManagedObject(TManagedObject body, string? xCumulocityProcessingMode = null, CancellationToken cToken = default) where TManagedObject : ManagedObject; - /// - /// Retrieve the total number of managed objects
- /// Retrieve the total number of managed objects (for example, devices, assets, etc.) registered in your tenant, or a subset based on queries.
- /// - ///
Required roles
- /// ROLE_INVENTORY_READ is not required, but if the current user doesn't have this role, the response will contain the number of inventory objects accessible for the user. - /// - ///
Response Codes
- /// The following table gives an overview of the possible response codes and their meanings:
- /// - /// - /// HTTP 200 The request has succeeded and the number of managed objects is sent in the response.

- ///
- ///
- /// - /// HTTP 401 Authentication information is missing or invalid.

- ///
- ///
- ///
- ///
- /// Propagates notification that operations should be canceled.
- /// Search for a specific child addition and list all the groups to which it belongs.
- /// Search for a specific child asset and list all the groups to which it belongs.
- /// Search for a specific child device and list all the groups to which it belongs.
- /// A characteristic which identifies a managed object or event, for example, geolocation, electricity sensor, relay state.
- /// The managed object IDs to search for.
ⓘ Info: If you query for multiple IDs at once, comma-separate the values.
- /// Username of the owner of the managed objects.
- /// Search for managed objects where any property value is equal to the given one. Only string values are supported.
- /// The type of managed object to search for.
- /// - Task GetNumberOfManagedObjects(string? childAdditionId = null, string? childAssetId = null, string? childDeviceId = null, string? fragmentType = null, List? ids = null, string? owner = null, string? text = null, string? type = null, CancellationToken cToken = default) ; - /// /// Retrieve a specific managed object
/// Retrieve a specific managed object (for example, device, group, template) by a given ID.
@@ -227,6 +195,7 @@ public interface IManagedObjectsApi /// Remove a specific managed object
/// Remove a specific managed object (for example, device) by a given ID.
/// ⓘ Info: Inventory DELETE requests are not synchronous. The response could be returned before the delete request has been completed. This may happen especially when the deleted managed object has a lot of associated data. After sending the request, the platform starts deleting the associated data in an asynchronous way. Finally, the requested managed object is deleted after all associated data has been deleted.
+ /// ⓘ Info: By default, the delete operation is always propagated to the subgroups, but only if the deleted object is a group.
/// ///
Required roles
/// ROLE_INVENTORY_ADMIN OR owner of the source OR MANAGE_OBJECT_ADMIN permission on the source diff --git a/Client/Com/Cumulocity/Client/Api/IMeasurementsApi.cs b/Client/Com/Cumulocity/Client/Api/IMeasurementsApi.cs index 12d8394..c0ace4b 100644 --- a/Client/Com/Cumulocity/Client/Api/IMeasurementsApi.cs +++ b/Client/Com/Cumulocity/Client/Api/IMeasurementsApi.cs @@ -166,7 +166,7 @@ public interface IMeasurementsApi /// Remove measurement collections
/// Remove measurement collections specified by query parameters.
/// DELETE requests are not synchronous. The response could be returned before the delete request has been completed. This may happen especially when there are a lot of measurements to be deleted.
- /// ⚠️ Important: DELETE requires at least one of the following parameters: source, dateFrom, dateTo.
+ /// ⚠️ Important: Note that it is possible to call this endpoint without providing any parameter - it may result in deleting all measurements and it is not recommended.
/// In case of enhanced time series measurements, both dateFrom and dateTo parameters must be truncated to full hours (for example, 2022-08-19T14:00:00.000Z), otherwise an error will be returned.The fragmentType parameter allows to delete measurements only by a measurement fragment when enhanced time series measurements are used.It's not possible to delete by a custom (non-measurement) fragment.
/// Example for a valid measurement value fragment:
/// /// Remove a stored certificate
- /// Remove a stored trusted certificate (by a given fingerprint) from a specific tenant (by a given ID).
+ /// Remove a stored trusted certificate (by a given fingerprint) from a specific tenant (by a given ID).When a trusted certificate is deleted, the established MQTT connection to all devices that are using the corresponding certificate are closed.
/// ///
Required roles
/// (ROLE_TENANT_MANAGEMENT_ADMIN OR ROLE_TENANT_ADMIN) AND (is the current tenant OR is the management tenant) @@ -332,72 +332,4 @@ public interface ITrustedCertificatesApi /// Propagates notification that operations should be canceled.
/// Task GenerateVerificationCode(string tenantId, string fingerprint, CancellationToken cToken = default) ; - - /// - /// Verify a certificate chain via file upload
- /// Verify a device certificate chain against a specific tenant. Max chain length support is 10.The tenant ID is optional and this api will be further enhanced to resolve the tenant from the chain in future release.
- /// - ///
Required roles
- /// (ROLE_TENANT_MANAGEMENT_ADMIN) AND (is the current tenant OR is current management tenant) - /// - ///
Response Codes
- /// The following table gives an overview of the possible response codes and their meanings:
- /// - /// - /// HTTP 200 The request has succeeded and the validation result is sent in the response.

- ///
- ///
- /// - /// HTTP 400 Unable to parse certificate chain.

- ///
- ///
- /// - /// HTTP 403 Not enough permissions/roles to perform this operation.

- ///
- ///
- /// - /// HTTP 404 The tenant ID does not exist.

- ///
- ///
- ///
- ///
- /// - /// File to be uploaded.
- /// Propagates notification that operations should be canceled.
- /// - Task ValidateChainByFileUpload(string tenantId, byte[] file, CancellationToken cToken = default) ; - - /// - /// Verify a certificate chain via HTTP header
- /// Verify a device certificate chain against a specific tenant. Max chain length support is 6.The tenant ID is optional and this api will be further enhanced to resolve the tenant from the chain in future release.
- /// - ///
Required roles
- /// (ROLE_TENANT_MANAGEMENT_ADMIN) AND (is the current tenant OR is current management tenant) - /// - ///
Response Codes
- /// The following table gives an overview of the possible response codes and their meanings:
- /// - /// - /// HTTP 200 The request has succeeded and the validation result is sent in the response.

- ///
- ///
- /// - /// HTTP 400 Unable to parse certificate chain.

- ///
- ///
- /// - /// HTTP 403 Not enough permissions/roles to perform this operation.

- ///
- ///
- /// - /// HTTP 404 The tenant ID does not exist.

- ///
- ///
- ///
- ///
- /// Used to send a tenant ID.
- /// Used to send a certificate chain in the header. Separate the chain with , and also each 64 bit block with (a space character).
- /// Propagates notification that operations should be canceled.
- /// - Task ValidateChainByHeader(string? xCumulocityTenantId = null, string? xCumulocityClientCertChain = null, CancellationToken cToken = default) ; } diff --git a/Client/Com/Cumulocity/Client/Api/IUsageStatisticsApi.cs b/Client/Com/Cumulocity/Client/Api/IUsageStatisticsApi.cs index 41b8354..c044f49 100644 --- a/Client/Com/Cumulocity/Client/Api/IUsageStatisticsApi.cs +++ b/Client/Com/Cumulocity/Client/Api/IUsageStatisticsApi.cs @@ -98,6 +98,74 @@ namespace Client.Com.Cumulocity.Client.Api; ///
Microservice usage statistics
/// The microservice usage statistics gathers information on the resource usage for tenants for each subscribed application which are collected on a daily base.
/// The microservice usage's information is stored in the resources object.
+///
Frequently asked questions
+///
Which requests are counted as general "requestCount"?
+/// All requests which the platform receives are counted, including,for example, UI requests, microservices requests, device requests and agents requests. Only a few internal endpoints are not counted:
+/// +/// +/// /health (and all endpoints including this URI fragment, like /tenant/health)
+///
+///
+/// +/// /application/currentApplication (and all subresources, like /application/currentApplication/subscriptions)
+///
+///
+/// +/// /tenant/limit
+///
+///
+/// +/// /devicecontrol/deviceCredentials
+///
+///
+/// +/// /inventory/templates (and all subresources)
+///
+///
+///
+///
My devices are not sending any data, but "requestCount" is increasing, and the total number is really big. Why is this happening?
+/// Not only device requests are counted. Every user interaction with UI applications generates some requests to the backend API. Additionally you may have subscribed standard or custom microservices, which also regularly send requests to the platform.
+/// Example: If you have four microservices and each microservice sends five requests per minute, this setup creates 4 * 5 * 60 * 24 = 28800 requests per day. Similar numbers arise if there are multiple users working with the given tenant UI concurrently.
+///
Which requests are counted as "deviceRequestCount"?
+/// All requests from "requestCount" except the following:
+/// +/// +/// Tenant API requests
+///
+///
+/// +/// Application API requests
+///
+///
+/// +/// User API requests
+///
+///
+/// +/// Requests with the proper HTTP header X-Cumulocity-Application-Key, matching the application key of one of the applications used by a particular tenant
+///
+///
+///
+/// The exclusion of the APIs in the list above means that requests to endpoints which start with the mentioned API prefixes are not counted. For example, for the Tenant API the following endpoints are not counted (the list is incomplete):
+/// +/// +/// /tenant/tenants
+///
+///
+/// +/// /tenant/currentTenant
+///
+///
+/// +/// /tenant/statistics
+///
+///
+/// +/// /tenant/options
+///
+///
+///
+/// ⓘ Info: Each microservice and web application must include the X-Cumulocity-Application-Key header in all requests.Otherwise such requests are counted as device requests which incorrectly affects the "deviceRequestCount" usage metric.
///
/// public interface IUsageStatisticsApi diff --git a/Client/Com/Cumulocity/Client/Api/ManagedObjectsApi.cs b/Client/Com/Cumulocity/Client/Api/ManagedObjectsApi.cs index 3a8f9b4..95662bd 100644 --- a/Client/Com/Cumulocity/Client/Api/ManagedObjectsApi.cs +++ b/Client/Com/Cumulocity/Client/Api/ManagedObjectsApi.cs @@ -106,33 +106,6 @@ public ManagedObjectsApi(HttpClient httpClient) return await JsonSerializerWrapper.DeserializeAsync(responseStream, cancellationToken: cToken).ConfigureAwait(false);; } - /// - public async Task GetNumberOfManagedObjects(string? childAdditionId = null, string? childAssetId = null, string? childDeviceId = null, string? fragmentType = null, List? ids = null, string? owner = null, string? text = null, string? type = null, CancellationToken cToken = default) - { - const string resourcePath = "/inventory/managedObjects/count"; - var uriBuilder = new UriBuilder(new Uri(_httpClient.BaseAddress ?? new Uri(resourcePath), resourcePath)); - var queryString = HttpUtility.ParseQueryString(uriBuilder.Query); - queryString.TryAdd("childAdditionId", childAdditionId); - queryString.TryAdd("childAssetId", childAssetId); - queryString.TryAdd("childDeviceId", childDeviceId); - queryString.TryAdd("fragmentType", fragmentType); - queryString.TryAdd("ids", ids, false); - queryString.TryAdd("owner", owner); - queryString.TryAdd("text", text); - queryString.TryAdd("type", type); - uriBuilder.Query = queryString.ToString(); - using var request = new HttpRequestMessage - { - Method = HttpMethod.Get, - RequestUri = new Uri(uriBuilder.ToString()) - }; - request.Headers.TryAddWithoutValidation("Accept", "application/vnd.com.nsn.cumulocity.error+json, text/plain,application/json"); - using var response = await _httpClient.SendAsync(request: request, cancellationToken: cToken).ConfigureAwait(false); - await response.EnsureSuccessStatusCodeWithContentInfo().ConfigureAwait(false); - await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); - return await JsonSerializerWrapper.DeserializeAsync(responseStream, cancellationToken: cToken).ConfigureAwait(false);; - } - /// public async Task GetManagedObject(string id, bool? skipChildrenNames = null, bool? withChildren = null, bool? withChildrenCount = null, bool? withParents = null, CancellationToken cToken = default) where TManagedObject : ManagedObject { diff --git a/Client/Com/Cumulocity/Client/Api/TrustedCertificatesApi.cs b/Client/Com/Cumulocity/Client/Api/TrustedCertificatesApi.cs index a4aafa9..5e70ea7 100644 --- a/Client/Com/Cumulocity/Client/Api/TrustedCertificatesApi.cs +++ b/Client/Com/Cumulocity/Client/Api/TrustedCertificatesApi.cs @@ -230,49 +230,4 @@ public TrustedCertificatesApi(HttpClient httpClient) await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); return await JsonSerializerWrapper.DeserializeAsync(responseStream, cancellationToken: cToken).ConfigureAwait(false);; } - - /// - public async Task ValidateChainByFileUpload(string tenantId, byte[] file, CancellationToken cToken = default) - { - const string resourcePath = "/tenant/tenants/verify-cert-chain/fileUpload"; - var uriBuilder = new UriBuilder(new Uri(_httpClient.BaseAddress ?? new Uri(resourcePath), resourcePath)); - var requestContent = new MultipartFormDataContent(); - var fileContentTenantId = new StringContent(JsonSerializerWrapper.Serialize(tenantId)); - fileContentTenantId.Headers.ContentType = MediaTypeHeaderValue.Parse("text/plain"); - requestContent.Add(fileContentTenantId, "tenantId"); - var fileContentFile = new ByteArrayContent(file); - fileContentFile.Headers.ContentType = MediaTypeHeaderValue.Parse("text/plain"); - requestContent.Add(fileContentFile, "file"); - using var request = new HttpRequestMessage - { - Content = requestContent, - Method = HttpMethod.Post, - RequestUri = new Uri(uriBuilder.ToString()) - }; - request.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data"); - request.Headers.TryAddWithoutValidation("Accept", "application/vnd.com.nsn.cumulocity.error+json, application/json"); - using var response = await _httpClient.SendAsync(request: request, cancellationToken: cToken).ConfigureAwait(false); - await response.EnsureSuccessStatusCodeWithContentInfo().ConfigureAwait(false); - await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); - return await JsonSerializerWrapper.DeserializeAsync(responseStream, cancellationToken: cToken).ConfigureAwait(false);; - } - - /// - public async Task ValidateChainByHeader(string? xCumulocityTenantId = null, string? xCumulocityClientCertChain = null, CancellationToken cToken = default) - { - const string resourcePath = "/tenant/tenants/verify-cert-chain"; - var uriBuilder = new UriBuilder(new Uri(_httpClient.BaseAddress ?? new Uri(resourcePath), resourcePath)); - using var request = new HttpRequestMessage - { - Method = HttpMethod.Post, - RequestUri = new Uri(uriBuilder.ToString()) - }; - request.Headers.TryAddWithoutValidation("X-Cumulocity-TenantId", xCumulocityTenantId); - request.Headers.TryAddWithoutValidation("X-Cumulocity-Client-Cert-Chain", xCumulocityClientCertChain); - request.Headers.TryAddWithoutValidation("Accept", "application/vnd.com.nsn.cumulocity.error+json, application/json"); - using var response = await _httpClient.SendAsync(request: request, cancellationToken: cToken).ConfigureAwait(false); - await response.EnsureSuccessStatusCodeWithContentInfo().ConfigureAwait(false); - await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); - return await JsonSerializerWrapper.DeserializeAsync(responseStream, cancellationToken: cToken).ConfigureAwait(false);; - } } diff --git a/Client/Com/Cumulocity/Client/Api/UsageStatisticsApi.cs b/Client/Com/Cumulocity/Client/Api/UsageStatisticsApi.cs index 1c79128..095aef1 100644 --- a/Client/Com/Cumulocity/Client/Api/UsageStatisticsApi.cs +++ b/Client/Com/Cumulocity/Client/Api/UsageStatisticsApi.cs @@ -105,6 +105,74 @@ namespace Client.Com.Cumulocity.Client.Api; ///
Microservice usage statistics
/// The microservice usage statistics gathers information on the resource usage for tenants for each subscribed application which are collected on a daily base.
/// The microservice usage's information is stored in the resources object.
+///
Frequently asked questions
+///
Which requests are counted as general "requestCount"?
+/// All requests which the platform receives are counted, including,for example, UI requests, microservices requests, device requests and agents requests. Only a few internal endpoints are not counted:
+/// +/// +/// /health (and all endpoints including this URI fragment, like /tenant/health)
+///
+///
+/// +/// /application/currentApplication (and all subresources, like /application/currentApplication/subscriptions)
+///
+///
+/// +/// /tenant/limit
+///
+///
+/// +/// /devicecontrol/deviceCredentials
+///
+///
+/// +/// /inventory/templates (and all subresources)
+///
+///
+///
+///
My devices are not sending any data, but "requestCount" is increasing, and the total number is really big. Why is this happening?
+/// Not only device requests are counted. Every user interaction with UI applications generates some requests to the backend API. Additionally you may have subscribed standard or custom microservices, which also regularly send requests to the platform.
+/// Example: If you have four microservices and each microservice sends five requests per minute, this setup creates 4 * 5 * 60 * 24 = 28800 requests per day. Similar numbers arise if there are multiple users working with the given tenant UI concurrently.
+///
Which requests are counted as "deviceRequestCount"?
+/// All requests from "requestCount" except the following:
+/// +/// +/// Tenant API requests
+///
+///
+/// +/// Application API requests
+///
+///
+/// +/// User API requests
+///
+///
+/// +/// Requests with the proper HTTP header X-Cumulocity-Application-Key, matching the application key of one of the applications used by a particular tenant
+///
+///
+///
+/// The exclusion of the APIs in the list above means that requests to endpoints which start with the mentioned API prefixes are not counted. For example, for the Tenant API the following endpoints are not counted (the list is incomplete):
+/// +/// +/// /tenant/tenants
+///
+///
+/// +/// /tenant/currentTenant
+///
+///
+/// +/// /tenant/statistics
+///
+///
+/// +/// /tenant/options
+///
+///
+///
+/// ⓘ Info: Each microservice and web application must include the X-Cumulocity-Application-Key header in all requests.Otherwise such requests are counted as device requests which incorrectly affects the "deviceRequestCount" usage metric.
///
/// public sealed class UsageStatisticsApi : IUsageStatisticsApi diff --git a/Client/Com/Cumulocity/Client/Model/AuthConfig.cs b/Client/Com/Cumulocity/Client/Model/AuthConfig.cs index 10d55a8..c366cde 100644 --- a/Client/Com/Cumulocity/Client/Model/AuthConfig.cs +++ b/Client/Com/Cumulocity/Client/Model/AuthConfig.cs @@ -174,13 +174,6 @@ public sealed class AuthConfig [JsonPropertyName("visibleOnLoginPage")] public bool? VisibleOnLoginPage { get; set; } - /// - /// A configuration for authentication with an access token from the authorization server.
- ///
- /// - [JsonPropertyName("externalTokenConfig")] - public ExternalTokenConfig? PExternalTokenConfig { get; set; } - public AuthConfig() { } @@ -309,13 +302,6 @@ public sealed class DynamicMapping [JsonPropertyName("mappings")] public List PMappings { get; set; } = new List(); - /// - /// Represents rules used to assign inventory roles.
- ///
- /// - [JsonPropertyName("inventoryMappings")] - public List PInventoryMappings { get; set; } = new List(); - /// /// Configuration of the mapping.
///
@@ -330,13 +316,6 @@ public sealed class Configuration [JsonPropertyName("mapRolesOnlyForNewUser")] public bool? MapRolesOnlyForNewUser { get; set; } - /// - /// If set to true, dynamic access mapping is only managed for global roles, applications and inventory roles which are listed in the configuration. Others remain unchanged.
- ///
- /// - [JsonPropertyName("manageRolesOnlyFromAccessMapping")] - public bool? ManageRolesOnlyFromAccessMapping { get; set; } - public override string ToString() { return JsonSerializerWrapper.Serialize(this, JsonSerializerWrapper.ToStringJsonSerializerOptions); @@ -351,7 +330,7 @@ public sealed class Mappings { /// - /// Represents a predicate for verification. It acts as a condition which is necessary to assign a user to the given groups, permit access to the specified applications or to assign specific inventory roles to device groups.
+ /// Represents a predicate for verification. It acts as a condition which is necessary to assign a user to the given groups and permit access to the specified applications.
///
/// [JsonPropertyName("when")] @@ -377,60 +356,6 @@ public override string ToString() } } - /// - /// Represents information of mapping access to inventory roles.
- ///
- /// - public sealed class InventoryMappings - { - - /// - /// Represents a predicate for verification. It acts as a condition which is necessary to assign a user to the given groups, permit access to the specified applications or to assign specific inventory roles to device groups.
- ///
- /// - [JsonPropertyName("when")] - public JSONPredicateRepresentation? When { get; set; } - - /// - /// List of the OAuth inventory assignments.
- ///
- /// - [JsonPropertyName("thenInventoryRoles")] - public List PThenInventoryRoles { get; set; } = new List(); - - /// - /// Represents inventory roles for a specific device group.
- ///
- /// - public sealed class ThenInventoryRoles - { - - /// - /// A unique identifier for the managed object for which the roles are assigned.
- ///
- /// - [JsonPropertyName("managedObject")] - public string? ManagedObject { get; set; } - - /// - /// List of the inventory roles' identifiers.
- ///
- /// - [JsonPropertyName("roleIds")] - public List RoleIds { get; set; } = new List(); - - public override string ToString() - { - return JsonSerializerWrapper.Serialize(this, JsonSerializerWrapper.ToStringJsonSerializerOptions); - } - } - - public override string ToString() - { - return JsonSerializerWrapper.Serialize(this, JsonSerializerWrapper.ToStringJsonSerializerOptions); - } - } - public override string ToString() { return JsonSerializerWrapper.Serialize(this, JsonSerializerWrapper.ToStringJsonSerializerOptions); @@ -669,105 +594,6 @@ public override string ToString() } - /// - /// A configuration for authentication with an access token from the authorization server.
- ///
- /// - public sealed class ExternalTokenConfig - { - - /// - /// Indicates whether authentication is enabled or disabled.
- ///
- /// - [JsonPropertyName("enabled")] - public bool? Enabled { get; set; } - - /// - /// Points to the claim of the access token from the authorization server that must be used as the username in the Cumulocity IoT platform.
- ///
- /// - [JsonPropertyName("userOrAppIdConfig")] - public UserOrAppIdConfig? PUserOrAppIdConfig { get; set; } - - /// - /// If set to true, the access token is validated against the authorization server by way of introspection or user info request.
- ///
- /// - [JsonPropertyName("validationRequired")] - public bool? ValidationRequired { get; set; } - - /// - /// The method of validation of the access token.
- ///
- /// - [JsonPropertyName("validationMethod")] - public ValidationMethod? PValidationMethod { get; set; } - - [JsonPropertyName("tokenValidationRequest")] - public RequestRepresentation? TokenValidationRequest { get; set; } - - /// - /// The frequency (in Minutes) in which Cumulocity sends a validation request to authorization server. The recommended frequency is 1 minute.
- ///
- /// - [JsonPropertyName("accessTokenValidityCheckIntervalInMinutes")] - public int? AccessTokenValidityCheckIntervalInMinutes { get; set; } - - /// - /// The method of validation of the access token.
- ///
- /// - [JsonConverter(typeof(EnumConverterFactory))] - public enum ValidationMethod - { - [EnumMember(Value = "INTROSPECTION")] - INTROSPECTION, - [EnumMember(Value = "USERINFO")] - USERINFO - } - - /// - /// Points to the claim of the access token from the authorization server that must be used as the username in the Cumulocity IoT platform.
- ///
- /// - public sealed class UserOrAppIdConfig - { - - /// - /// Used only if useConstantValue is set to true.
- ///
- /// - [JsonPropertyName("constantValue")] - public string? ConstantValue { get; set; } - - /// - /// The name of the field containing the JWT.
- ///
- /// - [JsonPropertyName("jwtField")] - public string? JwtField { get; set; } - - /// - /// Not recommended. If set to true, all users share a single account in the Cumulocity IoT platform.
- ///
- /// - [JsonPropertyName("useConstantValue")] - public bool? UseConstantValue { get; set; } - - public override string ToString() - { - return JsonSerializerWrapper.Serialize(this, JsonSerializerWrapper.ToStringJsonSerializerOptions); - } - } - - - public override string ToString() - { - return JsonSerializerWrapper.Serialize(this, JsonSerializerWrapper.ToStringJsonSerializerOptions); - } - } - public override string ToString() { return JsonSerializerWrapper.Serialize(this, JsonSerializerWrapper.ToStringJsonSerializerOptions); diff --git a/Client/Com/Cumulocity/Client/Model/CurrentUser.cs b/Client/Com/Cumulocity/Client/Model/CurrentUser.cs index 1dbb2aa..f11f17a 100644 --- a/Client/Com/Cumulocity/Client/Model/CurrentUser.cs +++ b/Client/Com/Cumulocity/Client/Model/CurrentUser.cs @@ -111,7 +111,7 @@ public sealed class CurrentUser /// [System.Obsolete("This property might be removed in future releases.", false)] [JsonPropertyName("devicePermissions")] - public DeprecatedDevicePermissions? DevicePermissions { get; set; } + public DevicePermissions? PDevicePermissions { get; set; } public override string ToString() { diff --git a/Client/Com/Cumulocity/Client/Model/DeprecatedDevicePermissions.cs b/Client/Com/Cumulocity/Client/Model/DevicePermissionOwners.cs similarity index 61% rename from Client/Com/Cumulocity/Client/Model/DeprecatedDevicePermissions.cs rename to Client/Com/Cumulocity/Client/Model/DevicePermissionOwners.cs index c312f6b..cd75af7 100644 --- a/Client/Com/Cumulocity/Client/Model/DeprecatedDevicePermissions.cs +++ b/Client/Com/Cumulocity/Client/Model/DevicePermissionOwners.cs @@ -1,11 +1,12 @@ // -// DeprecatedDevicePermissions.cs +// DevicePermissionOwners.cs // CumulocityCoreLibrary // // Copyright (c) 2014-2023 Software AG, Darmstadt, Germany and/or Software AG USA Inc., Reston, VA, USA, and/or its subsidiaries and/or its affiliates and/or their licensors. // Use, reproduction, transfer, publication or disclosure is prohibited except as specifically provided for in your License Agreement with Software AG. // +using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; using System.Runtime.Serialization; @@ -14,12 +15,18 @@ namespace Client.Com.Cumulocity.Client.Model; /// -/// An object with a list of the user's device permissions.
+/// A list of device permissions.
///
/// -public sealed class DeprecatedDevicePermissions +public sealed class DevicePermissionOwners where TCustomProperties : CustomProperties { + [JsonPropertyName("users")] + public List> Users { get; set; } = new List>(); + + [JsonPropertyName("groups")] + public List> Groups { get; set; } = new List>(); + public override string ToString() { return JsonSerializerWrapper.Serialize(this, JsonSerializerWrapper.ToStringJsonSerializerOptions); diff --git a/Client/Com/Cumulocity/Client/Model/DevicePermissions.cs b/Client/Com/Cumulocity/Client/Model/DevicePermissions.cs index 7b782de..4930863 100644 --- a/Client/Com/Cumulocity/Client/Model/DevicePermissions.cs +++ b/Client/Com/Cumulocity/Client/Model/DevicePermissions.cs @@ -15,17 +15,21 @@ namespace Client.Com.Cumulocity.Client.Model; /// -/// A list of device permissions.
+/// An object with a list of the user's device permissions.
///
/// -public sealed class DevicePermissions where TCustomProperties : CustomProperties +public sealed class DevicePermissions { - [JsonPropertyName("users")] - public List> Users { get; set; } = new List>(); - - [JsonPropertyName("groups")] - public List> Groups { get; set; } = new List>(); + [JsonPropertyName("additionalProperties")] + public IDictionary?> AdditionalProperties { get; set; } = new Dictionary?>(); + + [JsonIgnore] + public List? this[string key] + { + get => AdditionalProperties[key]; + set => AdditionalProperties[key] = value; + } public override string ToString() { diff --git a/Client/Com/Cumulocity/Client/Model/Group.cs b/Client/Com/Cumulocity/Client/Model/Group.cs index a63c1a9..139eb03 100644 --- a/Client/Com/Cumulocity/Client/Model/Group.cs +++ b/Client/Com/Cumulocity/Client/Model/Group.cs @@ -44,7 +44,7 @@ public sealed class Group where TCustomProperties : CustomPro /// [System.Obsolete("This property might be removed in future releases.", false)] [JsonPropertyName("devicePermissions")] - public DeprecatedDevicePermissions? DevicePermissions { get; set; } + public DevicePermissions? PDevicePermissions { get; set; } /// /// A unique identifier for this group.
diff --git a/Client/Com/Cumulocity/Client/Model/JSONPredicateRepresentation.cs b/Client/Com/Cumulocity/Client/Model/JSONPredicateRepresentation.cs index 5e9a857..0e97b70 100644 --- a/Client/Com/Cumulocity/Client/Model/JSONPredicateRepresentation.cs +++ b/Client/Com/Cumulocity/Client/Model/JSONPredicateRepresentation.cs @@ -16,7 +16,7 @@ namespace Client.Com.Cumulocity.Client.Model; /// -/// Represents a predicate for verification. It acts as a condition which is necessary to assign a user to the given groups, permit access to the specified applications or to assign specific inventory roles to device groups.
+/// Represents a predicate for verification. It acts as a condition which is necessary to assign a user to the given groups and permit access to the specified applications.
///
/// public sealed class JSONPredicateRepresentation diff --git a/Client/Com/Cumulocity/Client/Model/NotificationSubscription.cs b/Client/Com/Cumulocity/Client/Model/NotificationSubscription.cs index a51496e..4a01be8 100644 --- a/Client/Com/Cumulocity/Client/Model/NotificationSubscription.cs +++ b/Client/Com/Cumulocity/Client/Model/NotificationSubscription.cs @@ -142,7 +142,10 @@ public sealed class SubscriptionFilter { /// - /// The Notifications are available for Alarms, Alarms with children, Device control, Events, Events with children, Inventory and Measurements for the mo context and for Alarms, Events and Inventory for the tenant context. Alternatively, the wildcard * can be used to match all the permissible APIs within the bound context.
+ /// For the mo (Managed object) context, notifications from the alarms, alarmsWithChildren, events, eventsWithChildren, managedobjects (Inventory), measurements and operations (Device control) APIs can be subscribed to.
+ /// The alarmsWithChildren and eventsWithChildren APIs subscribe to alarms and events respectively from the managed object identified by the source.id field, and all of its descendant managed objects.
+ /// For the tenant context, notifications from the alarms, events and managedobjects (Inventory) APIs can be subscribed to.
+ /// For all contexts, the * (wildcard) value can be used to subscribe to notifications from all of the available APIs in that context.
/// ⓘ Info: The wildcard * cannot be used in conjunction with other values.
/// ⓘ Info: When filtering Events in the tenant context it is required to also specify the typeFilter.
///
@@ -151,9 +154,9 @@ public sealed class SubscriptionFilter public List Apis { get; set; } = new List(); /// - /// Used to match the type property of the data. An OData expression must be provided.
- /// ⓘ Info: The use of a type attribute is assumed, for example when using only a string literal 'c8y_Temperature' it is equivalent to a type eq 'c8y_Temperature' OData expression.
- /// ⓘ Info: Currently only the or operator is allowed in the expression mode. Example usage is 'c8y_Temperature' or 'c8y_Pressure' which will match all the data with types c8y_Temperature or c8y_Pressure.
+ /// Used to match the type property of the data. This must either be a string to match one specific type exactly, or be an or OData expression, allowing the filter to match any one of a number of types.
+ /// ⓘ Info: The use of a type attribute is assumed, for example when using only a string literal 'c8y_Temperature' (or using c8y_Temperature, as quotes can be omitted when matching a single type) it is equivalent to a type eq 'c8y_Temperature' OData expression.
+ /// ⓘ Info: Currently only the or operator is allowed when using an OData expression. Example usage is 'c8y_Temperature' or 'c8y_Pressure' which will match all the data with types c8y_Temperature or c8y_Pressure.
///
/// [JsonPropertyName("typeFilter")] diff --git a/Client/Com/Cumulocity/Client/Model/UpdatedDevicePermissions.cs b/Client/Com/Cumulocity/Client/Model/UpdatedDevicePermissions.cs new file mode 100644 index 0000000..7bebe04 --- /dev/null +++ b/Client/Com/Cumulocity/Client/Model/UpdatedDevicePermissions.cs @@ -0,0 +1,74 @@ +// +// UpdatedDevicePermissions.cs +// CumulocityCoreLibrary +// +// Copyright (c) 2014-2023 Software AG, Darmstadt, Germany and/or Software AG USA Inc., Reston, VA, USA, and/or its subsidiaries and/or its affiliates and/or their licensors. +// Use, reproduction, transfer, publication or disclosure is prohibited except as specifically provided for in your License Agreement with Software AG. +// + +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Runtime.Serialization; +using Client.Com.Cumulocity.Client.Supplementary; + +namespace Client.Com.Cumulocity.Client.Model; + +/// +/// A list of device permissions.
+///
+/// +public sealed class UpdatedDevicePermissions +{ + + [JsonPropertyName("users")] + public List PUsers { get; set; } = new List(); + + [JsonPropertyName("groups")] + public List PGroups { get; set; } = new List(); + + public sealed class Users + { + + [JsonPropertyName("userName")] + public string? UserName { get; set; } + + /// + /// An object with a list of the user's device permissions.
+ ///
+ /// + [System.Obsolete("This property might be removed in future releases.", false)] + [JsonPropertyName("devicePermissions")] + public DevicePermissions? PDevicePermissions { get; set; } + + public override string ToString() + { + return JsonSerializerWrapper.Serialize(this, JsonSerializerWrapper.ToStringJsonSerializerOptions); + } + } + + public sealed class Groups + { + + [JsonPropertyName("id")] + public string? Id { get; set; } + + /// + /// An object with a list of the user's device permissions.
+ ///
+ /// + [System.Obsolete("This property might be removed in future releases.", false)] + [JsonPropertyName("devicePermissions")] + public DevicePermissions? PDevicePermissions { get; set; } + + public override string ToString() + { + return JsonSerializerWrapper.Serialize(this, JsonSerializerWrapper.ToStringJsonSerializerOptions); + } + } + + public override string ToString() + { + return JsonSerializerWrapper.Serialize(this, JsonSerializerWrapper.ToStringJsonSerializerOptions); + } +} diff --git a/Client/Com/Cumulocity/Client/Model/User.cs b/Client/Com/Cumulocity/Client/Model/User.cs index f1ff7b9..deb51d4 100644 --- a/Client/Com/Cumulocity/Client/Model/User.cs +++ b/Client/Com/Cumulocity/Client/Model/User.cs @@ -173,7 +173,7 @@ public sealed class User where TCustomProperties : CustomProp /// [System.Obsolete("This property might be removed in future releases.", false)] [JsonPropertyName("devicePermissions")] - public DeprecatedDevicePermissions? DevicePermissions { get; set; } + public DevicePermissions? PDevicePermissions { get; set; } /// /// Indicates the password strength. The value can be GREEN, YELLOW or RED for decreasing password strengths.
diff --git a/Client/Com/Cumulocity/Client/Supplementary/CumulocityCoreLibrary.cs b/Client/Com/Cumulocity/Client/Supplementary/CumulocityCoreLibrary.cs index 9742d8d..4e53063 100644 --- a/Client/Com/Cumulocity/Client/Supplementary/CumulocityCoreLibrary.cs +++ b/Client/Com/Cumulocity/Client/Supplementary/CumulocityCoreLibrary.cs @@ -67,7 +67,7 @@ public CumulocityCoreLibrary(IHttpClientFactory clientFactory, string clientName public IIdentityFactory Identity => _lazyIdentity.Value; public IDeviceControlFactory DeviceControl => _lazyDeviceControl.Value; public IInventoryFactory Inventory => _lazyInventory.Value; - + public class ApplicationsFactory: IApplicationsFactory { private readonly Lazy _lazyApplicationsApi; diff --git a/Client/Com/Cumulocity/Client/Supplementary/JsonSerializerWrapper.cs b/Client/Com/Cumulocity/Client/Supplementary/JsonSerializerWrapper.cs index 8115e7b..a21b4ed 100644 --- a/Client/Com/Cumulocity/Client/Supplementary/JsonSerializerWrapper.cs +++ b/Client/Com/Cumulocity/Client/Supplementary/JsonSerializerWrapper.cs @@ -40,7 +40,7 @@ public static void Serialize(Utf8JsonWriter writer, TValue value, JsonSe public static ValueTask DeserializeAsync(Stream utf8Stream, CancellationToken cancellationToken = default) { - return JsonSerializer.DeserializeAsync(utf8Stream, JsonSerializerOptions, cancellationToken: cancellationToken); + return utf8Stream.Length == 0 ? default : JsonSerializer.DeserializeAsync(utf8Stream, JsonSerializerOptions, cancellationToken: cancellationToken); } public static T? Deserialize(string jsonString, JsonSerializerOptions? options = null) diff --git a/Test/Com/Cumulocity/Client/Api/ManagedObjectsApiTest.cs b/Test/Com/Cumulocity/Client/Api/ManagedObjectsApiTest.cs index 8d1b6e5..c9e3d7b 100644 --- a/Test/Com/Cumulocity/Client/Api/ManagedObjectsApiTest.cs +++ b/Test/Com/Cumulocity/Client/Api/ManagedObjectsApiTest.cs @@ -46,12 +46,4 @@ public async void TestGetManagedObjects() var response = await api.GetManagedObjects(); Debug.Assert(response != null); } - - [TestMethod] - public async void TestGetNumberOfManagedObjects() - { - var api = new ManagedObjectsApi(HttpClient!); - var response = await api.GetNumberOfManagedObjects(); - Debug.Assert(response != null); - } }