PushSharp关注点分离

爱荷华

我目前正在使用C#Web应用程序,并且正在尝试使用PushSharp软件包来获取推送通知。我在项目的Global.asax文件中拥有用于推送通知的所有代码,但始终收到错误消息:

The collection has been marked as complete with regards to additions.

这是我的Global.asax文件:

using BYC.Models;
using BYC.Models.Enums;
using Newtonsoft.Json.Linq;
using PushSharp.Apple;
using PushSharp.Google;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace BYC
{
    public class WebApiApplication : System.Web.HttpApplication
    {

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
        protected void Application_End()
        {
            PushBrokerSingleton pbs = new PushBrokerSingleton();
            pbs.SendQueuedNotifications();
        }
    }

    public sealed class PushBrokerSingleton
    {
        private static ApnsServiceBroker Apns { get; set; }
        private static GcmServiceBroker Gcm { get; set; }
        private static bool ApnsStarted = false;
        private static bool GcmStarted = false;
        private static object AppleSyncVar = new object();
        private static object GcmSyncVar = new object();

        private static readonly log4net.ILog log = log4net.LogManager.GetLogger
(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public PushBrokerSingleton()
        {
            if (Apns == null)
        {
            string thumbprint = (AppSettings.Instance["APNS:Thumbprint"]);
            X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);

            ApnsConfiguration.ApnsServerEnvironment production = Convert.ToBoolean(AppSettings.Instance["APNS:Production"]) ?
                ApnsConfiguration.ApnsServerEnvironment.Production : ApnsConfiguration.ApnsServerEnvironment.Sandbox;

            X509Certificate2 appleCert = store.Certificates
              .Cast<X509Certificate2>()
              .SingleOrDefault(c => string.Equals(c.Thumbprint, thumbprint, StringComparison.OrdinalIgnoreCase));


            ApnsConfiguration apnsConfig = new ApnsConfiguration(production, appleCert);
            Apns = new ApnsServiceBroker(apnsConfig);
            Apns.OnNotificationFailed += (notification, aggregateEx) => {

                aggregateEx.Handle(ex => {

                    // See what kind of exception it was to further diagnose
                    if (ex is ApnsNotificationException)
                    {
                        var notificationException = ex as ApnsNotificationException;

                        // Deal with the failed notification
                        var apnsNotification = notificationException.Notification;
                        var statusCode = notificationException.ErrorStatusCode;

                        log.Error($"Notification Failed: ID={apnsNotification.Identifier}, Code={statusCode}");

                    }
                    else {
                        // Inner exception might hold more useful information like an ApnsConnectionException           
                        log.Error($"Notification Failed for some (Unknown Reason) : {ex.InnerException}");
                    }

                    // Mark it as handled
                    return true;
                });
            };

            Apns.OnNotificationSucceeded += (notification) => {
                log.Info("Notification Successfully Sent to: " + notification.DeviceToken);
            };
        }
        if(Gcm == null)
        {
            GcmConfiguration gcmConfig = new GcmConfiguration(AppSettings.Instance["GCM:Token"]);
            Gcm = new GcmServiceBroker(gcmConfig);
        }
    }

    public bool QueueNotification(Notification notification, Device device)
    {
        if (!ApnsStarted)
        {
            ApnsStarted = true;
            lock (AppleSyncVar)
            {
                Apns.Start();
            }
        }
        if(!GcmStarted)
        {
            GcmStarted = true;
            lock (GcmSyncVar)
            {
                Gcm.Start();
            }
        }
        switch (device.PlatformType)
        {
            case PlatformType.iOS:
                return QueueApplePushNotification(notification, device.PushRegistrationToken);
            case PlatformType.Android:
                return QueueAndroidPushNotification(notification, device.PushRegistrationToken);
            default: return false;
        }
    }

    private bool QueueApplePushNotification(Notification notification, string pushNotificationToken)
    {
        string appleJsonFormat = "{\"aps\": {\"alert\":" + '"' + notification.Subject + '"' + ",\"sound\": \"default\", \"badge\": " + notification.BadgeNumber + "}}";
        lock (AppleSyncVar)
        {
            Apns.QueueNotification(new ApnsNotification()
            {
                DeviceToken = pushNotificationToken,
                Payload = JObject.Parse(appleJsonFormat)
            });
        }
        return true;
    }

    private bool QueueAndroidPushNotification(Notification notification, string pushNotificationToken)
    {
        string message = "{\"alert\":\"" + notification.Subject + "\",\"badge\":" + notification.BadgeNumber + "\"}";
        lock (GcmSyncVar)
        {
            Gcm.QueueNotification(new GcmNotification()
            {
                RegistrationIds = new List<string>
                         {
                             pushNotificationToken
                         },
                Data = JObject.Parse(message),
                Notification = JObject.Parse(message)
            });
        }
        return true;
    }

    public void SendQueuedNotifications()
    {
        if(Apns != null)
        {
            if (ApnsStarted)
            {
                lock(AppleSyncVar){
                    Apns.Stop();
                    log.Info("Sent Apns Notifications");
                    ApnsStarted = false;
                }
            }
        }
        if(Gcm != null)
        {
            if (GcmStarted)
            {
                lock (GcmSyncVar)
                {
                    Gcm.Stop();
                    log.Info("Sent Gcm Notifications");
                    GcmStarted = false;
                }
            }
        }
    }
}

}

雷德思

:当你尝试和重用服务代理(例如一个实例发生ApnsServiceBroker这)Stop()已经呼吁。

我猜您Application_End在某个时候Application_Start被调用并再次被调用,但是由于PushBrokerSingleton.Apns它不为null(这是一个静态字段,因此即使应用程序已停止/启动,它也必须存在),因此永远不会重新创建它。

PushSharp很难使ASP.NET模式很好地工作,某种服务守护程序会更好。

主要问题是您的应用程序可能在您不期望的情况下被回收或终止。同一应用程序中不相关的请求可能会导致您的流程中断,或者您的AppDomain可能会被删除。如果发生这种情况,并且经纪人的Stop()呼叫无法成功结束,则可能会丢失一些排队的消息。这是一篇有关一些警告的出色文章:http : //haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx/在实践中,这可能没什么大不了的,您当然可以减轻它的一部分,但请记住这一点。

说了这么多,我想一个简单的解决将是创建一个新的实例PushBrokerSingleton.Apns,并PushBrokerSingleton.Gcm在你的Application_Start这可能会给您带来其他问题,因此我不确定这是否是正确的解决方案,但可以解决在Stop()调用代理后不应重用代理的问题

我还将考虑添加某种方式来“重置”集合。我不确定在.Stop()结束后自动执行此操作是否是个好主意,但我可能会考虑添加一种.Reset()或类似类型的方法来实现此目的。无论如何,现在完全可以创建一个新的代理实例。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

PushSharp关注点分离

来自分类Dev

关注点分离

来自分类Dev

WCF关注点分离与DRY

来自分类Dev

Java,Netbeans和关注点分离

来自分类Dev

WPF中的关注点分离

来自分类Dev

AngularJS和分析-分离关注点

来自分类Dev

两类关注点分离

来自分类Dev

Java,Netbeans和关注点分离

来自分类Dev

WPF中的关注点分离

来自分类Dev

Mongo DB如何分离关注点

来自分类Dev

Docker关注点/服务分离

来自分类Dev

Symfony 3 - 关注点分离?

来自分类Dev

角度和语义标记/关注点分离

来自分类Dev

角度和语义标记/关注点分离

来自分类Dev

在windowscope中拆分CDI bean,以分离关注点

来自分类Dev

CakePHP 3中的MVC-模型与视图之间的关注点分离

来自分类Dev

ASP.NET MVC:普通/管理员用户的关注点分离

来自分类Dev

为什么在这种情况下我需要分离关注点?

来自分类Dev

清理视图红宝石逻辑并将关注点分离到模型/控制器中

来自分类Dev

iOS Swift Xcode 6对情节提要中的视图控制器委托的关注点分离

来自分类Dev

基于类的环境中关注点/代码结构的分离(以C#为例)

来自分类Dev

测试消耗其他组件的组件时,关注点分离是什么?

来自分类Dev

使用ng-pattern进行验证是否违反关注点分离?

来自分类Dev

Winforms / Devexpress / Tab控件关注点分离/常规代码布局

来自分类Dev

iOS Swift Xcode 6对情节提要中的视图控制器委托的关注点分离

来自分类Dev

使用实体框架7和asp.net 5保持关注点分离

来自分类Dev

基于类的环境中关注点/代码结构的分离(以C#为例)

来自分类Dev

对嵌套关注点的循环依赖

来自分类Dev

重新分配关注点