web-serviceswindows-phone-7push-notificationmpns

Send a push notification from a windows phone device to webservice


I have a question about the push notification service of the Windows Phone 7 device: I can now send a push notification, using a web application to a phone, changing the data of the tile. But the problem is: when I start the app, I need to display the URI in the debugger output, and then copy-paste it inside the web application, which in turn will contact the MPNS, which is fine for an update, once to a single phone. But I want to create a webservice that can make multiple calls automatically, retrieve the URI of the application ( which changes after closing-and-opening the app, I think ) and send a push notification to it. But I haven't found an MSDN - topic that deals with this. They just use commends, saying : "to be replaced later with the URI needed." So my question is: how do I use the phone to send such a message to the webservice, respond to it, and connect to the phone again, handling such request? and also: do I need an authenticated webservice, or is there a debug version?

This is what I have thus far :

  /// <summary>
    /// Setup a connection with a webservice, in order to update a shell, either a toast- or a tile shell.
    /// </summary>
    /// <param name="shellType">The type of shell you wish to update</param>
    public void SetupShellChannel ( ShellBindType shellType )
    {
        //holds the push notification that is created. Since we can only have one notification channel open at any one time, 
        //we will need to check for existance. That is why, the channelName shouldn't be changed
        HttpNotificationChannel _httpChannel = HttpNotificationChannel.Find( _channelName );

        //if the _httpChannel was not found ( read: does not exist )
        if ( _httpChannel == null )
        {
            _httpChannel = new HttpNotificationChannel( _channelName  );
            _httpChannel.Open( );

            //because there is more than one shelltype we can open, we will use a switch to call the method we seek
            BindToShell( _httpChannel, shellType );
        }
            //Only one push notification service is allowed per application, so we cannot send a tile notification, as well as 
            //a toast message notification. When we attempt this, we get a InvalidOperationException
        else
        { 
            //in this case, the _httpChannel did already exist, but the problem is, we cannot just add the eventHandlers, 
            //because there is the danger that it didn't exist, and we would get a null pointer exception.
            //_httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>( httpChannel_ChannelUriUpdated );
            //_httpChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>( httpChannel_ErrorOccurred );

            //For testing purposes, we now display the URI to the user, and as output. Normally, we would pass this URI back to the webserver
            System.Diagnostics.Debug.WriteLine( _httpChannel.ChannelUri.ToString( ) );
        }

        //if ( _httpChannel.ChannelUri )

        //When the URI is updated, we want this to be sent to the server as well, so we know that the adress has changed, 
        //and don't just send data somewhere into the void. Also, when encountering an error, we want to show the user when 
        //an error has occured.
        _httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>( HttpChannel_ChannelUriUpdated );
        _httpChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>( HttpChannel_ErrorOccurred );
    }

    //here, also we would return the URI to the server, but for debugging purposes, we display them to the user.
    void HttpChannel_ChannelUriUpdated( object sender, NotificationChannelUriEventArgs e )
    {
        Deployment.Current.Dispatcher.BeginInvoke( ( ) => 
        {
            System.Diagnostics.Debug.WriteLine( e.ChannelUri.ToString( ) );
            MessageBox.Show( String.Format( "the URI is {0}", e.ChannelUri.ToString( ) ) );
        } );
    }

    private void BindToShell( HttpNotificationChannel channel, ShellBindType shellType )
    {
        switch ( shellType )
        {
            case ShellBindType.BindToShellTile:
                channel.BindToShellTile( );
                break;
            case ShellBindType.BindToShellToast:
                channel.BindToShellToast( );
                break;
        }        
    }

    void HttpChannel_ErrorOccurred( object sender, NotificationChannelErrorEventArgs e )
    {
        //getting an error would be caugth here, and then displayed to the user.
        Deployment.Current.Dispatcher.BeginInvoke( ( ) =>
            {
                MessageBox.Show( String.Format( "A push notification {0} error occured. {1}{(2)}{3}", 
                    e.ErrorType, e.Message, e.ErrorCode, e.ErrorAdditionalData ) );
            } );
    }

Solution

  • Ok I understand your question. What I have done is once I get teh URI from MPNS, I call a web method on a service with this as a parameter - Subscribe(int subscriberId, Uri channelUri);

    So you need to make sure you generate a subscriberId in your app to identify a user and store it in Isolated Storage. This can be a GUID.

    The onus is now upon hte server to save the Subscriber to Uri mapping in persistant storage.

    Also you need to provide UnSubscribe method for user to opt out of the push notification. This is one of the certification requirement for Push notifications.

    Now about your second question - Yes, you would need to secure your services - you dont want to be handling with unknown requests.

    What i do personally, divide it into 2 services - Publishing service and subscription service. The Publishing service will send out hte notifications while subscription will have the subscribe/unsubscribe methods.