/WP7.1/Templates/VB/WPCloud.Mem/WindowsPhoneCloud.Web/Services/SamplePushUserRegistrationService.vb
Visual Basic | 241 lines | 177 code | 40 blank | 24 comment | 4 complexity | 51dd494372d521392b3786ea788fd3cd MD5 | raw file
- ' ----------------------------------------------------------------------------------
- ' Microsoft Developer & Platform Evangelism
- '
- ' Copyright (c) Microsoft Corporation. All rights reserved.
- '
- ' THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
- ' EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
- ' OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
- ' ----------------------------------------------------------------------------------
- ' The example companies, organizations, products, domain names,
- ' e-mail addresses, logos, people, places, and events depicted
- ' herein are fictitious. No association with any real company,
- ' organization, product, domain name, email address, logo, person,
- ' places, or events is intended or should be inferred.
- ' ----------------------------------------------------------------------------------
-
- Imports WindowsPhone.Recipes.Push.Messages
- Imports Microsoft.WindowsAzure.StorageClient
- Imports Microsoft.WindowsAzure
- Imports Microsoft.Samples.WindowsPhoneCloud.Web.UserAccountWrappers
- Imports Microsoft.Samples.WindowsPhoneCloud.Web.Models
- Imports Microsoft.Samples.WindowsPhoneCloud.Web.Infrastructure
- Imports System.ServiceModel.Web
- Imports System.ServiceModel.Activation
- Imports System.ServiceModel
- Imports System.Net
- Imports System.Globalization
- #If ACS Then
- Imports Microsoft.IdentityModel.Claims
- #End If
- Namespace Services
- <ServiceBehavior(IncludeExceptionDetailInFaults:=False), AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Required)>
- Public Class SamplePushUserRegistrationService
- Implements ISamplePushUserRegistrationService
- Private ReadOnly context As HttpContextBase
- Private ReadOnly pushUserEndpointsRepository As IPushUserEndpointsRepository
- Private ReadOnly cloudQueueClient As CloudQueueClient
- Private ReadOnly webOperationContext As WebOperationContext
-
- #If ACS Then
- Public Sub New()
- Me.New(New HttpContextWrapper(HttpContext.Current), WebOperationContext.Current, New UserTablesServiceContext(), Nothing)
- End Sub
-
- <CLSCompliant(False)>
- Public Sub New(ByVal context As HttpContextBase, ByVal webOperationContext As WebOperationContext, ByVal pushUserEndpointsRepository As IPushUserEndpointsRepository, ByVal cloudQueueClient As CloudQueueClient)
- If (context Is Nothing) AndAlso (HttpContext.Current Is Nothing) Then
- Throw New ArgumentNullException("context", "Context cannot be null if not running on a Web context.")
- End If
-
- If pushUserEndpointsRepository Is Nothing Then
- Throw New ArgumentNullException("pushUserEndpointsRepository", "PushUserEndpoints repository cannot be null.")
- End If
-
- If (cloudQueueClient Is Nothing) AndAlso (GetStorageAccountFromConfigurationSetting() Is Nothing) Then
- Throw New ArgumentNullException("cloudQueueClient", "Cloud Queue Client cannot be null if no configuration is loaded.")
- End If
-
- Me.cloudQueueClient = If(cloudQueueClient, GetStorageAccountFromConfigurationSetting().CreateCloudQueueClient())
- Me.webOperationContext = webOperationContext
- Me.context = context
- Me.pushUserEndpointsRepository = pushUserEndpointsRepository
- End Sub
-
- Private ReadOnly Property UserId() As String
- Get
- Dim identity = TryCast(HttpContext.Current.User.Identity, IClaimsIdentity)
- Return identity.Claims.Single(Function(c) c.ClaimType = ClaimTypes.NameIdentifier).Value
- End Get
- End Property
- #Else
- Private ReadOnly formsAuth As IFormsAuthentication
- Private ReadOnly membershipService As IMembershipService
-
- Public Sub New()
- Me.New(New HttpContextWrapper(HttpContext.Current), webOperationContext.Current, New FormsAuthenticationService(), New AccountMembershipService(), New UserTablesServiceContext(), Nothing)
- End Sub
-
- <CLSCompliant(False)>
- Public Sub New(ByVal context As HttpContextBase, ByVal webOperationContext As WebOperationContext, ByVal formsAuth As IFormsAuthentication, ByVal membershipService As IMembershipService, ByVal pushUserEndpointsRepository As IPushUserEndpointsRepository, ByVal cloudQueueClient As CloudQueueClient)
- If (context Is Nothing) AndAlso (HttpContext.Current Is Nothing) Then
- Throw New ArgumentNullException("context", "Context cannot be null if not running on a Web context.")
- End If
-
- If pushUserEndpointsRepository Is Nothing Then
- Throw New ArgumentNullException("pushUserEndpointsRepository", "PushUserEndpoints repository cannot be null.")
- End If
-
- If formsAuth Is Nothing Then
- Throw New ArgumentNullException("formsAuth", "Forms Authentication service cannot be null.")
- End If
-
- If membershipService Is Nothing Then
- Throw New ArgumentNullException("membershipService", "Membership service cannot be null.")
- End If
-
- If (cloudQueueClient Is Nothing) AndAlso (GetStorageAccountFromConfigurationSetting() Is Nothing) Then
- Throw New ArgumentNullException("cloudQueueClient", "Cloud Queue Client cannot be null if no configuration is loaded.")
- End If
-
- Me.cloudQueueClient = If(cloudQueueClient, GetStorageAccountFromConfigurationSetting().CreateCloudQueueClient())
- Me.webOperationContext = webOperationContext
- Me.context = context
- Me.pushUserEndpointsRepository = pushUserEndpointsRepository
- Me.formsAuth = formsAuth
- Me.membershipService = membershipService
- End Sub
-
- Private ReadOnly Property UserId() As String
- Get
- Dim ticketValue As String = Nothing
-
- Dim cookie = Me.context.Request.Cookies(Me.formsAuth.FormsCookieName)
- If cookie IsNot Nothing Then
- ' From cookie.
- ticketValue = cookie.Value
- ElseIf Me.context.Request.Headers("AuthToken") IsNot Nothing Then
- ' From HTTP header.
- ticketValue = Me.context.Request.Headers("AuthToken")
- End If
-
- If Not String.IsNullOrEmpty(ticketValue) Then
- Dim ticket As FormsAuthenticationTicket
-
- Try
- ticket = Me.formsAuth.Decrypt(ticketValue)
- Catch
- Throw New WebFaultException(Of String)("The authorization ticket cannot be decrypted.", HttpStatusCode.Unauthorized)
- End Try
-
- If ticket IsNot Nothing Then
- Return Me.membershipService.GetUser(New FormsIdentity(ticket).Name).ProviderUserKey.ToString()
- Else
- Throw New WebFaultException(Of String)("The authorization token is no longer valid.", HttpStatusCode.Unauthorized)
- End If
- Else
- Throw New WebFaultException(Of String)("Resource not found.", HttpStatusCode.NotFound)
- End If
- End Get
- End Property
- #End If
-
- Public Function Register(ByVal pushUserRegister As PushUserServiceRequest) As String Implements ISamplePushUserRegistrationService.Register
- ' Authenticate.
- Dim userId = Me.UserId
-
- Try
- Dim pushUserEndpoint = Me.pushUserEndpointsRepository.GetPushUserByApplicationAndDevice(pushUserRegister.ApplicationId, pushUserRegister.DeviceId)
- If pushUserEndpoint Is Nothing Then
- Dim newPushUserEndPoint = New PushUserEndpoint(pushUserRegister.ApplicationId, pushUserRegister.DeviceId) With {.ChannelUri = pushUserRegister.ChannelUri.ToString(), .UserId = userId}
- Me.pushUserEndpointsRepository.AddPushUserEndpoint(newPushUserEndPoint)
- Else
- ' If the user did not change the channel URI, then, there is nothing to update, otherwise, set the new connection status
- If (Not pushUserEndpoint.ChannelUri.Equals(pushUserRegister.ChannelUri.ToString())) OrElse (Not pushUserEndpoint.UserId.Equals(userId)) Then
- ' Update che channelUri for the UserEndpoint and reset status fields.
- pushUserEndpoint.ChannelUri = pushUserRegister.ChannelUri.ToString()
- pushUserEndpoint.UserId = userId
- End If
-
- Me.pushUserEndpointsRepository.UpdatePushUserEndpoint(pushUserEndpoint)
- End If
- Catch exception As Exception
- Throw New WebFaultException(Of String)(String.Format(CultureInfo.InvariantCulture, "There was an error registering the Push Notification Endpoint: {0}", exception.Message), HttpStatusCode.InternalServerError)
- End Try
-
- Return "Success"
- End Function
-
- Public Function Unregister(ByVal pushUserUnregister As PushUserServiceRequest) As String Implements ISamplePushUserRegistrationService.Unregister
- ' Authenticate.
- Dim userId = Me.UserId
-
- Try
- Me.pushUserEndpointsRepository.RemovePushUserEndpoint(New PushUserEndpoint(pushUserUnregister.ApplicationId, pushUserUnregister.DeviceId) With {.UserId = userId})
- Catch exception As Exception
- Throw New WebFaultException(Of String)(String.Format(CultureInfo.InvariantCulture, "There was an error unregistering the Push Notification Endpoint: {0}", exception.Message), HttpStatusCode.InternalServerError)
- End Try
-
- Return "Success"
- End Function
-
- Public Function GetUpdates(ByVal applicationId As String, ByVal deviceId As String) As String() Implements ISamplePushUserRegistrationService.GetUpdates
- ' Authenticate.
- Dim userId = Me.UserId
-
- Me.webOperationContext.OutgoingResponse.Headers.Add("Cache-Control", "no-cache")
- Dim userEndpoint = Me.pushUserEndpointsRepository.GetPushUserByApplicationAndDevice(applicationId, deviceId)
- Try
- Dim queueName = GetQueueName(applicationId, deviceId, userEndpoint.UserId)
- Dim queue = Me.cloudQueueClient.GetQueueReference(queueName)
- Dim messages = New List(Of String)()
- If queue.Exists() Then
- Dim message = queue.GetMessage()
- Do While message IsNot Nothing
- messages.Add(message.AsString)
- queue.DeleteMessage(message)
- message = queue.GetMessage()
- Loop
- End If
-
- Me.ResetTileNotificationCount(applicationId, deviceId)
-
- Return messages.ToArray()
- Catch exception As Exception
- Throw New WebFaultException(Of String)(String.Format(CultureInfo.InvariantCulture, "There was an error getting the push notification updates: {0}", exception.Message), HttpStatusCode.InternalServerError)
- End Try
- End Function
-
- Private Shared Function GetQueueName(ByVal applicationId As String, ByVal deviceId As String, ByVal userId As String) As String
- Dim uniqueName = String.Concat(applicationId, deviceId, userId)
-
- Return String.Concat("notification", uniqueName.GetHashCode())
- End Function
-
- Private Shared Function GetStorageAccountFromConfigurationSetting() As CloudStorageAccount
- Dim account As CloudStorageAccount = Nothing
-
- Try
- account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString")
- Catch e1 As InvalidOperationException
- account = Nothing
- End Try
-
- Return account
- End Function
-
- Private Sub ResetTileNotificationCount(ByVal applicationId As String, ByVal deviceId As String)
- Dim pushUserEndpoint = Me.pushUserEndpointsRepository.GetPushUserByApplicationAndDevice(applicationId, deviceId)
-
- pushUserEndpoint.TileCount = 0
-
- Dim tile = New TilePushNotificationMessage With {.SendPriority = MessageSendPriority.High, .Count = pushUserEndpoint.TileCount}
-
- ' Send a new tile notification message to reset the count in the phone application.
- tile.SendAndHandleErrors(New Uri(pushUserEndpoint.ChannelUri))
-
- ' Save the updated count.
- Me.pushUserEndpointsRepository.UpdatePushUserEndpoint(pushUserEndpoint)
- End Sub
- End Class
- End Namespace