Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions .pubnub.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
name: c-sharp
version: "7.5.0"
version: "8.0.0"
schema: 1
scm: github.com/pubnub/c-sharp
changelog:
- date: 2025-10-27
version: v8.0.0
changes:
- type: feature
text: "BREAKING CHANGES: The HereNow method will return a maximum of 1000 occupants per channel. Previously, it was returning all occupants without limit parameter support. Use pagination through offset when more than 1000 occupants present in channel."
- type: bug
text: "Discard use of gcm and replaced with fcm for push notification service type of google. Removed mpns support."
- type: improvement
text: "Added new tests for duplicate subscribe requests."
- date: 2025-09-01
version: v7.5.0
changes:
Expand Down Expand Up @@ -943,7 +952,7 @@ features:
- QUERY-PARAM
supported-platforms:
-
version: Pubnub 'C#' 7.5.0
version: Pubnub 'C#' 8.0.0
platforms:
- Windows 10 and up
- Windows Server 2008 and up
Expand All @@ -954,7 +963,7 @@ supported-platforms:
- .Net Framework 4.6.1+
- .Net Framework 6.0
-
version: PubnubPCL 'C#' 7.5.0
version: PubnubPCL 'C#' 8.0.0
platforms:
- Xamarin.Android
- Xamarin.iOS
Expand All @@ -974,7 +983,7 @@ supported-platforms:
- .Net Core
- .Net 6.0
-
version: PubnubUWP 'C#' 7.5.0
version: PubnubUWP 'C#' 8.0.0
platforms:
- Windows Phone 10
- Universal Windows Apps
Expand All @@ -998,7 +1007,7 @@ sdks:
distribution-type: source
distribution-repository: GitHub
package-name: Pubnub
location: https://github.com/pubnub/c-sharp/releases/tag/v7.5.0.0
location: https://github.com/pubnub/c-sharp/releases/tag/v8.0.0.0
requires:
-
name: ".Net"
Expand Down Expand Up @@ -1281,7 +1290,7 @@ sdks:
distribution-type: source
distribution-repository: GitHub
package-name: PubNubPCL
location: https://github.com/pubnub/c-sharp/releases/tag/v7.5.0.0
location: https://github.com/pubnub/c-sharp/releases/tag/v8.0.0.0
requires:
-
name: ".Net Core"
Expand Down Expand Up @@ -1640,7 +1649,7 @@ sdks:
distribution-type: source
distribution-repository: GitHub
package-name: PubnubUWP
location: https://github.com/pubnub/c-sharp/releases/tag/v7.5.0.0
location: https://github.com/pubnub/c-sharp/releases/tag/v8.0.0.0
requires:
-
name: "Universal Windows Platform Development"
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
v8.0.0 - October 27 2025
-----------------------------
- Added: bREAKING CHANGES: The HereNow method will return a maximum of 1000 occupants per channel. Previously, it was returning all occupants without limit parameter support. Use pagination through offset when more than 1000 occupants present in channel.

- Fixed: discard use of gcm and replaced with fcm for push notification service type of google. Removed mpns support.

- Modified: added new tests for duplicate subscribe requests.

v7.5.0 - September 01 2025
-----------------------------
- Fixed: fixed types of Meta and Actions in PNHistoryItemResult to not be objects but properly formatted Dictionaries.
Expand Down
10 changes: 5 additions & 5 deletions src/Api/PubnubApi/EndPoint/Access/GrantTokenOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ internal void GrantAccess(PNCallback<PNAccessManagerTokenResult> callback)
if (this.grantTTL <= 0) {
throw new MissingMemberException("Invalid TTL value");
}
logger?.Debug($"{GetType().Name} parameter validated.");
logger?.Trace($"{GetType().Name} parameter validated.");
RequestState<PNAccessManagerTokenResult> requestState = new RequestState<PNAccessManagerTokenResult>
{
Channels = pubnubResources.Channels.Keys.ToArray(),
Expand All @@ -194,14 +194,14 @@ internal void GrantAccess(PNCallback<PNAccessManagerTokenResult> callback)
if (!string.IsNullOrEmpty(responseString)) {
List<object> result = ProcessJsonResponse(requestState, responseString);
ProcessResponseCallbacks(result, requestState);
logger?.Info($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
}
} else {
int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message);
PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message);
PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerGrantToken, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error));
requestState.PubnubCallback.OnResponse(default(PNAccessManagerTokenResult), status);
logger?.Info($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
}
});
}
Expand Down Expand Up @@ -231,7 +231,7 @@ internal async Task<PNResult<PNAccessManagerTokenResult>> GrantAccess()
if (this.grantTTL <= 0) {
throw new MissingMemberException("Invalid TTL value");
}
logger?.Debug($"{GetType().Name} parameter validated.");
logger?.Trace($"{GetType().Name} parameter validated.");
RequestState<PNAccessManagerTokenResult> requestState = new RequestState<PNAccessManagerTokenResult>();
requestState.Channels = pubnubResources.Channels.Keys.ToArray();
requestState.ChannelGroups = pubnubResources.ChannelGroups.Keys.ToArray();
Expand Down Expand Up @@ -274,7 +274,7 @@ internal async Task<PNResult<PNAccessManagerTokenResult>> GrantAccess()
PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerGrantToken, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error));
returnValue.Status = status;
}
logger?.Info($"{GetType().Name} request finished with status code {returnValue.Status.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {returnValue.Status.StatusCode}");
return returnValue;
}

Expand Down
12 changes: 6 additions & 6 deletions src/Api/PubnubApi/EndPoint/Access/RevokeTokenOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ internal void RevokeAccess(PNCallback<PNAccessManagerRevokeTokenResult> callback
throw new MissingMemberException("Invalid secret key");
}

logger?.Debug($"{GetType().Name} parameter validated.");
logger?.Trace($"{GetType().Name} parameter validated.");
RequestState<PNAccessManagerRevokeTokenResult> requestState = new RequestState<PNAccessManagerRevokeTokenResult>
{
ResponseType = PNOperationType.PNAccessManagerRevokeToken,
Expand All @@ -80,14 +80,14 @@ internal void RevokeAccess(PNCallback<PNAccessManagerRevokeTokenResult> callback
if (!string.IsNullOrEmpty(responseString)) {
List<object> result = ProcessJsonResponse(requestState, responseString);
ProcessResponseCallbacks(result, requestState);
logger?.Info($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
}
} else {
int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message);
PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message);
PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerRevokeToken, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error));
requestState.PubnubCallback.OnResponse(default(PNAccessManagerRevokeTokenResult), status);
logger?.Info($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
}
});
}
Expand All @@ -97,7 +97,7 @@ internal async Task<PNResult<PNAccessManagerRevokeTokenResult>> RevokeAccess()
if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0) {
throw new MissingMemberException("Invalid secret key");
}
logger?.Debug($"{GetType().Name} parameter validated.");
logger?.Trace($"{GetType().Name} parameter validated.");
PNResult<PNAccessManagerRevokeTokenResult> returnValue = new PNResult<PNAccessManagerRevokeTokenResult>();
RequestState<PNAccessManagerRevokeTokenResult> requestState = new RequestState<PNAccessManagerRevokeTokenResult>();
requestState.ResponseType = PNOperationType.PNAccessManagerRevokeToken;
Expand Down Expand Up @@ -133,10 +133,10 @@ internal async Task<PNResult<PNAccessManagerRevokeTokenResult>> RevokeAccess()
} else {
int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message);
PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message);
PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerRevokeToken, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error));logger?.Debug($"{GetType().Name} request finished with status code {statusCode}");
PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerRevokeToken, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error));logger?.Trace($"{GetType().Name} request finished with status code {statusCode}");
returnValue.Status = status;
}
logger?.Info($"{GetType().Name} request finished with status code {returnValue.Status.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {returnValue.Status.StatusCode}");
return returnValue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ internal void AddChannelsToChannelGroup(string[] channels, string nameSpace, str
if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) {
throw new ArgumentException("Missing groupName");
}
logger?.Debug($"{GetType().Name} parameter validated.");
logger?.Trace($"{GetType().Name} parameter validated.");
RequestState<PNChannelGroupsAddChannelResult> requestState = new RequestState<PNChannelGroupsAddChannelResult>();
requestState.ResponseType = PNOperationType.PNAddChannelsToGroupOperation;
requestState.Channels = new string[] { };
Expand All @@ -101,14 +101,14 @@ internal void AddChannelsToChannelGroup(string[] channels, string nameSpace, str
if (!string.IsNullOrEmpty(responseString)) {
List<object> result = ProcessJsonResponse(requestState, responseString);
ProcessResponseCallbacks(result, requestState);
logger?.Info($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
}
} else {
int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message);
PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message);
PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAddChannelsToGroupOperation, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error));
requestState.PubnubCallback.OnResponse(default(PNChannelGroupsAddChannelResult), status);
logger?.Info($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
}
});
}
Expand All @@ -126,7 +126,7 @@ internal async Task<PNResult<PNChannelGroupsAddChannelResult>> AddChannelsToChan
if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) {
throw new ArgumentException("Missing groupName");
}
logger?.Debug($"{GetType().Name} parameter validated.");
logger?.Trace($"{GetType().Name} parameter validated.");
PNResult<PNChannelGroupsAddChannelResult> returnValue = new PNResult<PNChannelGroupsAddChannelResult>();
RequestState<PNChannelGroupsAddChannelResult> requestState = new RequestState<PNChannelGroupsAddChannelResult>();
requestState.ResponseType = PNOperationType.PNAddChannelsToGroupOperation;
Expand Down Expand Up @@ -165,7 +165,7 @@ internal async Task<PNResult<PNChannelGroupsAddChannelResult>> AddChannelsToChan
PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerRevokeToken, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error));
returnValue.Status = status;
}
logger?.Info($"{GetType().Name} request finished with status code {returnValue.Status.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {returnValue.Status.StatusCode}");
return returnValue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ internal void DeleteChannelGroup(string groupName, Dictionary<string, object> ex
if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) {
throw new ArgumentException("Missing groupName");
}
logger?.Debug($"{GetType().Name} parameter validated.");
logger?.Trace($"{GetType().Name} parameter validated.");
RequestState<PNChannelGroupsDeleteGroupResult> requestState = new RequestState<PNChannelGroupsDeleteGroupResult>();
requestState.ResponseType = PNOperationType.PNRemoveGroupOperation;
requestState.Channels = new string[] { };
Expand All @@ -85,14 +85,14 @@ internal void DeleteChannelGroup(string groupName, Dictionary<string, object> ex
if (!string.IsNullOrEmpty(responseString)) {
List<object> result = ProcessJsonResponse(requestState, responseString);
ProcessResponseCallbacks(result, requestState);
logger?.Info($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
}
} else {
int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message);
PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message);
PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNRemoveGroupOperation, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error));
requestState.PubnubCallback.OnResponse(default(PNChannelGroupsDeleteGroupResult), status);
logger?.Info($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
}
});
}
Expand All @@ -103,7 +103,7 @@ internal async Task<PNResult<PNChannelGroupsDeleteGroupResult>> DeleteChannelGro
throw new ArgumentException("Missing groupName");
}

logger?.Debug($"{GetType().Name} parameter validated.");
logger?.Trace($"{GetType().Name} parameter validated.");
PNResult<PNChannelGroupsDeleteGroupResult> returnValue = new PNResult<PNChannelGroupsDeleteGroupResult>();
RequestState<PNChannelGroupsDeleteGroupResult> requestState = new RequestState<PNChannelGroupsDeleteGroupResult>();
requestState.ResponseType = PNOperationType.PNRemoveGroupOperation;
Expand Down Expand Up @@ -142,7 +142,7 @@ internal async Task<PNResult<PNChannelGroupsDeleteGroupResult>> DeleteChannelGro
PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNRemoveGroupOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error));
returnValue.Status = status;
}
logger?.Info($"{GetType().Name} request finished with status code {returnValue.Status.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {returnValue.Status.StatusCode}");
return returnValue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ internal void GetAllChannelGroup(Dictionary<string, object> externalQueryParam,
requestState.GotJsonResponse = true;
if (!string.IsNullOrEmpty(responseString)) {
List<object> result = ProcessJsonResponse(requestState, responseString);
logger?.Debug($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
ProcessResponseCallbacks(result, requestState);
}
} else {
int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message);
PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message);
PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.ChannelGroupAllGet, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error));
requestState.PubnubCallback.OnResponse(default(PNChannelGroupsListAllResult), status);
logger?.Debug($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {requestState.Response?.StatusCode}");
}
});
}
Expand Down Expand Up @@ -128,7 +128,7 @@ internal async Task<PNResult<PNChannelGroupsListAllResult>> GetAllChannelGroup(D
PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.ChannelGroupAllGet, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error));
returnValue.Status = status;
}
logger?.Info($"{GetType().Name} request finished with status code {returnValue.Status.StatusCode}");
logger?.Trace($"{GetType().Name} request finished with status code {returnValue.Status.StatusCode}");
return returnValue;
}

Expand Down
Loading
Loading