Xamarin.iOS推送通知HTTP异常,找不到用于路径push / installations / installation_id的控制器

时间:2018-12-17 20:40:57

标签: azure push-notification xamarin.ios apple-push-notifications

我知道使用同一台设备进行生产和开发,或者涉及带有Azure的Push Notifications和Notifications Hubs,都会出现问题。

我设置方法的方式类似于iOS:

  1. 我在Azure中为生产设置了一个通知中心,该通知中心已连接到Azure中托管的一个Web api。
  2. Azure中用于开发的另一个通知中心已连接到Azure中托管的另一个Web api。
  3. 当我在开发中使用该应用程序时,在AppDelegate.cs中,我只是向开发中心注册,例如:

    var client = new MobileServiceClient(AppConstants.AZURE_DEVELOPMENT_WEB_API_URL);

  4. 当应用程序准备好进行生产时,我在AppDelegate.cs中向生产通知中心注册,例如:

    var client = newMobileServiceClient(AppConstants.AZURE_PRODUCTION_WEB_API_URL);

  5. 我当然会根据情况将Entitlements.plist aps-environment密钥修改为开发或生产版本。

这在一段时间内效果很好,但现在我在这一行中收到一个错误:

    try
    {
        // exception is triggered here:
        await client.GetPush().RegisterAsync(deviceToken, templates);                   
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);           
    }

错误是这样的:

2018-12-17 12:03:19.682 MyApp.iOS[7321:2007760] <!DOCTYPE html>
<html>
    <head>
        <title>The resource cannot be found.</title>
        <meta name="viewport" content="width=device-width" />
        <style>
         body {font-family:"Verdana";font-weight:normal;font-size: .7em;color:black;} 
         p {font-family:"Verdana";font-weight:normal;color:black;margin-top: -5px}
         b {font-family:"Verdana";font-weight:bold;color:black;margin-top: -5px}
         H1 { font-family:"Verdana";font-weight:normal;font-size:18pt;color:red }
         H2 { font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon }
         pre {font-family:"Consolas","Lucida Console",Monospace;font-size:11pt;margin:0;padding:0.5em;line-height:14pt}
         .marker {font-weight: bold; color: black;text-decoration: none;}
         .version {color: gray;}
         .error {margin-bottom: 10px;}
         .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }

 @media screen and (max-width: 639px) {
          pre { width: 440px; overflow: auto; white-space: pre-wrap; word-wrap: break-word; }
         }
         @media screen and (max-width: 479px) {
          pre { width: 280px; }
         }
        </style>
    </head>

    <body bgcolor="white">

            <span><H1>Server Error in '/' Application.<hr width=100% size=1 color=silver></H1>

            <h2> <i>The resource cannot be found.</i> </h2></span>

            <font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">

            <b> Description: </b>HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. &nbsp;Please review the following URL and make sure that it is spelled correctly.
            <br><br>

            <b> Requested URL: </b>/push/installations/53de1cd2-8ba5-403e-950a-f4a1631a5fae<br><br>

            <hr width=100% size=1 color=silver>

            <b>Version 
Information:</b>&nbsp;Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.7.3163.0

            </font>

    </body>
</html>
<!-- 
[HttpException]: The controller for path &#39;/push/installations/53de1cd2-8ba5-403e-950a-f4a1631a5fae&#39; was not found or does not implement IController.
   at System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType)
   at System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName)
   at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)
   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)
   at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncC
allback cb, Object extraData)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.<>c__DisplayClass285_0.<ExecuteStepImpl>b__0()
   at System.Web.HttpApplication.StepInvoker.Invoke(Action executionStep)
   at System.Web.HttpApplication.StepInvoker.<>c__DisplayClass4_0.<Invoke>b__0()
   at Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule.OnExecuteRequestStep(HttpContextBase context, Action step)
   at System.Web.HttpApplication.<>c__DisplayClass284_0.<OnExecuteRequestStep>b__0(Action nextStepAction)
   at System.Web.HttpApplication.StepInvoker.Invoke(Action executionStep)
   at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
--><!-- 
This error page might contain sensitive information because ASP.NET is configured to show verbose error messages using &lt;customErrors mode="Off"
/&gt;. Consider using &lt;customErrors mode="On"/&gt; or &lt;customErrors mode="RemoteOnly"/&gt; in production environments.-->
Thread finished: <Thread Pool> #13
The thread 0xd has exited with code 0 (0x0).

这是我的AppDelegate.cs中的代码:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {

            // This MobileServiceClient has been configured to communicate with the Azure Mobile App and
            // Azure Gateway using the application url. You're all set to start working with your Mobile App!
            //Microsoft.WindowsAzure.MobileServices.MobileServiceClient MyAppClient = new Microsoft.WindowsAzure.MobileServices.MobileServiceClient(
            //"https://myapp.azurewebsites.net");

            global::Xamarin.Forms.Forms.Init();

            //add azure support
            CurrentPlatform.Init();

            //add for using local database
            string dbName = "shakealarm_db.sqlite";
            string dbFolderPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "..", "Library");
            string dbFullPath = Path.Combine(dbFolderPath, dbName);

            //load application with overloaded constructor for local db path --> add dbFullPath as param to new App()
            LoadApplication(new App(dbFullPath, null));

            // first request permission to use push notifications
            RequestPushPermissionAsync();

            // going to store the contents of the notification in the options param
            // extract the content when app is active
            _launchOptions = options;

            return base.FinishedLaunching(app, options);
        }

        public override void OnActivated(UIApplication uiApplication)
        {
            base.OnActivated(uiApplication);

            //If app was not running and we come from a notification badge, the notification is
            if (_launchOptions != null && _launchOptions.ContainsKey(UIApplication.LaunchOptionsRemoteNotificationKey))
            {
                var notification = _launchOptions[UIApplication.LaunchOptionsRemoteNotificationKey] as NSDictionary;
                PresentNotification(notification);
            }
            _launchOptions = null;            
        }

        private async Task RequestPushPermissionAsync()
        {
            // Register for any type of notification (local or remote)
            var requestResult = await UNUserNotificationCenter.Current.RequestAuthorizationAsync(
                UNAuthorizationOptions.Alert
                | UNAuthorizationOptions.Badge
                | UNAuthorizationOptions.Sound);

            // request result produces two items, item1 and item2
            // Item1 = approved boolean
            bool approved = requestResult.Item1;
            NSError error = requestResult.Item2;

            if (error == null)
            {
                //Handle approval
                if (!approved)
                {
                    Console.Write("Permission to receive notifications was not granted.");
                    return;
                }

                // check if settings have been modified since last run to disallow permission for push notif.
                var currentSettings = await UNUserNotificationCenter.Current.GetNotificationSettingsAsync();
                if (currentSettings.AuthorizationStatus != UNAuthorizationStatus.Authorized)
                {
                    Console.WriteLine("Permissions were requested in the past but have been revoked(from settings)");
                    return;
                }

                // finally register for push notifications
                // starts an asycrhonous process, receives a token
                UIApplication.SharedApplication.RegisterForRemoteNotifications();
            }
            else
            {
                Console.Write($"Error requesting permissions: {error}.");
            }

        }

        public async override void RegisteredForRemoteNotifications(
            UIApplication application, NSData deviceToken)
        {
            if (deviceToken == null)
            {
                // can happen in rare conditions 
                return;
            }

            Console.WriteLine($"Token received: {deviceToken}");

            await SendRegistrationToServerAsync(deviceToken);
        }


        private async Task SendRegistrationToServerAsync(NSData deviceToken)
        {
            //this is the template/payload used by iOS. It contains the "messageParam"
            // that will be replaced by our service

            const string templateBodyAPNS = @"{
                                                ""aps"" : {
                                                    ""alert"" : ""$(messageParam)"",
                                                    ""mutable-content"": 1
                                                },
                                            }";


            var templates = new JObject();
            templates["genericMessage"] = new JObject
            {
                {"body", templateBodyAPNS }
            };

            // send registration to web api for PRODUCTION
            // var client = new MobileServiceClient(MyApp.App.MobileServiceUrl);

            // send registration to web api for DEVELOPMENT
            var client = new MobileServiceClient(AppConstants.AZURE_DEVELOPMENT_WEB_API_URL);       

            try
            {         
                // exception triggered here
                await client.GetPush().RegisterAsync(deviceToken, templates);                   
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);           
            }


            //get the installation id for Development
            Console.WriteLine("Installation id1: " + client.GetPush().InstallationId.ToString());
        }

因此,我几乎可以确定安装ID存在问题,这是因为我已经从商店下载了该应用,然后在开发中使用了相同的iPhone,并且混合了安装ID /注册以进行推送通知,但是下一步该怎么办?如何重置安装ID?

欢迎任何建议。

0 个答案:

没有答案