Genesys Cloud - Developer Community!

 View Only

Sign Up

NotificationHandler Exception - WebSocketSharp leads to System.PlatformNotSupportedException

  • 1.  NotificationHandler Exception - WebSocketSharp leads to System.PlatformNotSupportedException

    Posted 9 hours ago
    Edited by Carl Hansen 9 hours ago

    Hi Team,

    We have been running an Azure Function App for roughly 4 years without issue until 30/01/2026.

    The issue lies within registering a WebSocket connection for notification of Contact List Export endpoint. We get intermittent failures where some contact lists export without issue and some fail. On failure we run into the following error:

    Inner exception System.PlatformNotSupportedException handled at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw:
       at System.Action`1.BeginInvoke (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
       at WebSocketSharp.WebSocket.open (websocket-sharp, Version=1.0.2.59611, Culture=neutral, PublicKeyToken=5660b08a1845a91e)
       at WebSocketSharp.WebSocket.Connect (websocket-sharp, Version=1.0.2.59611, Culture=neutral, PublicKeyToken=5660b08a1845a91e)
       at PureCloudPlatform.Client.V2.Extensions.Notifications.NotificationHandler.ConnectSocket (PureCloudPlatform.Client.V2, Version=165.0.0.0, Culture=neutral, PublicKeyToken=null)
       at PureCloudPlatform.Client.V2.Extensions.Notifications.NotificationHandler..ctor (PureCloudPlatform.Client.V2, Version=165.0.0.0, Culture=neutral, PublicKeyToken=null)
       at App.Export.Run (App, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: C:\Export.cs:43)

    The function app is running .NET Framework 4.8 on a Windows App Service Plan.

    I have tried:

    • Restart the function app - did not work.
    • Check for Azure update to function app - no update in last 30 days.
    • Check for environment variables/configuration change - no change in last 30 days.
    • Check for changed code - no change for 2 years.
    • Check for expired credentials - did not expire.
    • Check change to role/permissions - no change.
    • Check for change to contact list IDs - no change.
    • Check PureCloud SDK for code updates - affected code not changed in SDK.

    I cannot figure out what is going on.

    Has there been any change on Genesys' side? Any assistance would be great please.

    The affected code is below:

    using System;
    using System.Net;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Blob;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    using PureCloudPlatform.Client.V2.Api;
    using PureCloudPlatform.Client.V2.Client;
    using PureCloudPlatform.Client.V2.Extensions;
    using PureCloudPlatform.Client.V2.Model;
    using PureCloudPlatform.Client.V2.Extensions.Notifications;
    using WebSocketSharp;
    using System.Threading;
    
    namespace App
    {
        public class Export
        {
            [FunctionName("Export")]
            public static HttpResponseMessage Run(
                [HttpTrigger(AuthorizationLevel.Function, "GET", Route = null)]
                HttpRequest req,
                ILogger logger)
            {
                PureCloudRegionHosts region = PureCloudRegionHosts.ap_southeast_1;
                Configuration.Default.ApiClient.setBasePath(region);
    
                var clientId = Environment.GetEnvironmentVariable("Id");
                var clientSecret = Environment.GetEnvironmentVariable("Secret");
                var accessTokenInfo = Configuration.Default.ApiClient.PostToken(clientId, clientSecret);
    
                Configuration.Default.AccessToken = accessTokenInfo.AccessToken;
    
                var accessToken = Configuration.Default.AccessToken;
                var apiInstance = new OutboundApi();
                var contactListId = req.Headers["contactListId"];
    /* fail */  var handler = new NotificationHandler(); // This is where the exception triggers
    
                // Get the contact list object
                var contactList = GetOutboundContactList(apiInstance, contactListId, logger);
    
                ResponseObject response = new ResponseObject();
    
                response.contactListId = contactList.Id;
                response.contactListName = contactList.Name;
                response.contactListSize = contactList.Size ?? 0;
    
                // Check if contact list is empty don't need to export if it is
                if (contactList.Size == 0)
                {
                    response.result = "Contact list is empty!";
    
                    return new HttpResponseMessage(HttpStatusCode.OK)
                    {
                        Content = new StringContent(JsonConvert.SerializeObject(response, Formatting.Indented), Encoding.UTF8, "application/json")
                    };
                }
    
                // This is so we get notified when the Contact List Export is complete
                // API user doesn't have a user context, so we can't programatically get
                // the user ID so it's hard-coded below
                handler.AddSubscription($"v2.users.oauth-id-abc-def.outbound.contactlists.{contactListId}.export", typeof(ContactlistDownloadReadyExportUri));
    
                PostOutboundContactListExport(apiInstance, contactListId, logger);
    
                string exportUri = null;
                // Wait until we get the notification that the export is complete
    
                int numOfAttempts = 1;
                do
                {
                    handler.NotificationReceived += (eventData) =>
                    {
                        if (eventData.GetType() == typeof(NotificationData<ContactlistDownloadReadyExportUri>))
                        {
                            var typedEventData = (NotificationData<ContactlistDownloadReadyExportUri>) eventData;
                            exportUri = typedEventData.EventBody.Uri;
                        }
                    };
    
                    numOfAttempts++;
                    // Delay for 5 seconds;
                    Thread.Sleep(5000);
    
                } while (exportUri.IsNullOrEmpty());
    
                var data = GetOutboundContactListExportData(accessToken, exportUri, logger);
    
                var fileName = $"{contactList.Name} Export {DateTime.Now.ToString("yyyyMMddHHmmss")}.csv";
                UploadFileToBlobStore(data, fileName, logger);
    
                response.blobContainerName = Environment.GetEnvironmentVariable("BlobContainerName");
                response.blobFileName = fileName;
                response.result = "Great success!";
    
                return new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new StringContent(JsonConvert.SerializeObject(response, Formatting.Indented), Encoding.UTF8, "application/json")
                };
            }
    
            /* More code... */
    }


    #PlatformSDK

    ------------------------------
    Carl Hansen
    ------------------------------