PageRenderTime 56ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  1. ' ----------------------------------------------------------------------------------
  2. ' Microsoft Developer & Platform Evangelism
  3. '
  4. ' Copyright (c) Microsoft Corporation. All rights reserved.
  5. '
  6. ' THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  7. ' EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
  8. ' OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  9. ' ----------------------------------------------------------------------------------
  10. ' The example companies, organizations, products, domain names,
  11. ' e-mail addresses, logos, people, places, and events depicted
  12. ' herein are fictitious. No association with any real company,
  13. ' organization, product, domain name, email address, logo, person,
  14. ' places, or events is intended or should be inferred.
  15. ' ----------------------------------------------------------------------------------
  16. Imports WindowsPhone.Recipes.Push.Messages
  17. Imports Microsoft.WindowsAzure.StorageClient
  18. Imports Microsoft.WindowsAzure
  19. Imports Microsoft.Samples.WindowsPhoneCloud.Web.UserAccountWrappers
  20. Imports Microsoft.Samples.WindowsPhoneCloud.Web.Models
  21. Imports Microsoft.Samples.WindowsPhoneCloud.Web.Infrastructure
  22. Imports System.ServiceModel.Web
  23. Imports System.ServiceModel.Activation
  24. Imports System.ServiceModel
  25. Imports System.Net
  26. Imports System.Globalization
  27. #If ACS Then
  28. Imports Microsoft.IdentityModel.Claims
  29. #End If
  30. Namespace Services
  31. <ServiceBehavior(IncludeExceptionDetailInFaults:=False), AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Required)>
  32. Public Class SamplePushUserRegistrationService
  33. Implements ISamplePushUserRegistrationService
  34. Private ReadOnly context As HttpContextBase
  35. Private ReadOnly pushUserEndpointsRepository As IPushUserEndpointsRepository
  36. Private ReadOnly cloudQueueClient As CloudQueueClient
  37. Private ReadOnly webOperationContext As WebOperationContext
  38. #If ACS Then
  39. Public Sub New()
  40. Me.New(New HttpContextWrapper(HttpContext.Current), WebOperationContext.Current, New UserTablesServiceContext(), Nothing)
  41. End Sub
  42. <CLSCompliant(False)>
  43. Public Sub New(ByVal context As HttpContextBase, ByVal webOperationContext As WebOperationContext, ByVal pushUserEndpointsRepository As IPushUserEndpointsRepository, ByVal cloudQueueClient As CloudQueueClient)
  44. If (context Is Nothing) AndAlso (HttpContext.Current Is Nothing) Then
  45. Throw New ArgumentNullException("context", "Context cannot be null if not running on a Web context.")
  46. End If
  47. If pushUserEndpointsRepository Is Nothing Then
  48. Throw New ArgumentNullException("pushUserEndpointsRepository", "PushUserEndpoints repository cannot be null.")
  49. End If
  50. If (cloudQueueClient Is Nothing) AndAlso (GetStorageAccountFromConfigurationSetting() Is Nothing) Then
  51. Throw New ArgumentNullException("cloudQueueClient", "Cloud Queue Client cannot be null if no configuration is loaded.")
  52. End If
  53. Me.cloudQueueClient = If(cloudQueueClient, GetStorageAccountFromConfigurationSetting().CreateCloudQueueClient())
  54. Me.webOperationContext = webOperationContext
  55. Me.context = context
  56. Me.pushUserEndpointsRepository = pushUserEndpointsRepository
  57. End Sub
  58. Private ReadOnly Property UserId() As String
  59. Get
  60. Dim identity = TryCast(HttpContext.Current.User.Identity, IClaimsIdentity)
  61. Return identity.Claims.Single(Function(c) c.ClaimType = ClaimTypes.NameIdentifier).Value
  62. End Get
  63. End Property
  64. #Else
  65. Private ReadOnly formsAuth As IFormsAuthentication
  66. Private ReadOnly membershipService As IMembershipService
  67. Public Sub New()
  68. Me.New(New HttpContextWrapper(HttpContext.Current), webOperationContext.Current, New FormsAuthenticationService(), New AccountMembershipService(), New UserTablesServiceContext(), Nothing)
  69. End Sub
  70. <CLSCompliant(False)>
  71. 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)
  72. If (context Is Nothing) AndAlso (HttpContext.Current Is Nothing) Then
  73. Throw New ArgumentNullException("context", "Context cannot be null if not running on a Web context.")
  74. End If
  75. If pushUserEndpointsRepository Is Nothing Then
  76. Throw New ArgumentNullException("pushUserEndpointsRepository", "PushUserEndpoints repository cannot be null.")
  77. End If
  78. If formsAuth Is Nothing Then
  79. Throw New ArgumentNullException("formsAuth", "Forms Authentication service cannot be null.")
  80. End If
  81. If membershipService Is Nothing Then
  82. Throw New ArgumentNullException("membershipService", "Membership service cannot be null.")
  83. End If
  84. If (cloudQueueClient Is Nothing) AndAlso (GetStorageAccountFromConfigurationSetting() Is Nothing) Then
  85. Throw New ArgumentNullException("cloudQueueClient", "Cloud Queue Client cannot be null if no configuration is loaded.")
  86. End If
  87. Me.cloudQueueClient = If(cloudQueueClient, GetStorageAccountFromConfigurationSetting().CreateCloudQueueClient())
  88. Me.webOperationContext = webOperationContext
  89. Me.context = context
  90. Me.pushUserEndpointsRepository = pushUserEndpointsRepository
  91. Me.formsAuth = formsAuth
  92. Me.membershipService = membershipService
  93. End Sub
  94. Private ReadOnly Property UserId() As String
  95. Get
  96. Dim ticketValue As String = Nothing
  97. Dim cookie = Me.context.Request.Cookies(Me.formsAuth.FormsCookieName)
  98. If cookie IsNot Nothing Then
  99. ' From cookie.
  100. ticketValue = cookie.Value
  101. ElseIf Me.context.Request.Headers("AuthToken") IsNot Nothing Then
  102. ' From HTTP header.
  103. ticketValue = Me.context.Request.Headers("AuthToken")
  104. End If
  105. If Not String.IsNullOrEmpty(ticketValue) Then
  106. Dim ticket As FormsAuthenticationTicket
  107. Try
  108. ticket = Me.formsAuth.Decrypt(ticketValue)
  109. Catch
  110. Throw New WebFaultException(Of String)("The authorization ticket cannot be decrypted.", HttpStatusCode.Unauthorized)
  111. End Try
  112. If ticket IsNot Nothing Then
  113. Return Me.membershipService.GetUser(New FormsIdentity(ticket).Name).ProviderUserKey.ToString()
  114. Else
  115. Throw New WebFaultException(Of String)("The authorization token is no longer valid.", HttpStatusCode.Unauthorized)
  116. End If
  117. Else
  118. Throw New WebFaultException(Of String)("Resource not found.", HttpStatusCode.NotFound)
  119. End If
  120. End Get
  121. End Property
  122. #End If
  123. Public Function Register(ByVal pushUserRegister As PushUserServiceRequest) As String Implements ISamplePushUserRegistrationService.Register
  124. ' Authenticate.
  125. Dim userId = Me.UserId
  126. Try
  127. Dim pushUserEndpoint = Me.pushUserEndpointsRepository.GetPushUserByApplicationAndDevice(pushUserRegister.ApplicationId, pushUserRegister.DeviceId)
  128. If pushUserEndpoint Is Nothing Then
  129. Dim newPushUserEndPoint = New PushUserEndpoint(pushUserRegister.ApplicationId, pushUserRegister.DeviceId) With {.ChannelUri = pushUserRegister.ChannelUri.ToString(), .UserId = userId}
  130. Me.pushUserEndpointsRepository.AddPushUserEndpoint(newPushUserEndPoint)
  131. Else
  132. ' If the user did not change the channel URI, then, there is nothing to update, otherwise, set the new connection status
  133. If (Not pushUserEndpoint.ChannelUri.Equals(pushUserRegister.ChannelUri.ToString())) OrElse (Not pushUserEndpoint.UserId.Equals(userId)) Then
  134. ' Update che channelUri for the UserEndpoint and reset status fields.
  135. pushUserEndpoint.ChannelUri = pushUserRegister.ChannelUri.ToString()
  136. pushUserEndpoint.UserId = userId
  137. End If
  138. Me.pushUserEndpointsRepository.UpdatePushUserEndpoint(pushUserEndpoint)
  139. End If
  140. Catch exception As Exception
  141. Throw New WebFaultException(Of String)(String.Format(CultureInfo.InvariantCulture, "There was an error registering the Push Notification Endpoint: {0}", exception.Message), HttpStatusCode.InternalServerError)
  142. End Try
  143. Return "Success"
  144. End Function
  145. Public Function Unregister(ByVal pushUserUnregister As PushUserServiceRequest) As String Implements ISamplePushUserRegistrationService.Unregister
  146. ' Authenticate.
  147. Dim userId = Me.UserId
  148. Try
  149. Me.pushUserEndpointsRepository.RemovePushUserEndpoint(New PushUserEndpoint(pushUserUnregister.ApplicationId, pushUserUnregister.DeviceId) With {.UserId = userId})
  150. Catch exception As Exception
  151. Throw New WebFaultException(Of String)(String.Format(CultureInfo.InvariantCulture, "There was an error unregistering the Push Notification Endpoint: {0}", exception.Message), HttpStatusCode.InternalServerError)
  152. End Try
  153. Return "Success"
  154. End Function
  155. Public Function GetUpdates(ByVal applicationId As String, ByVal deviceId As String) As String() Implements ISamplePushUserRegistrationService.GetUpdates
  156. ' Authenticate.
  157. Dim userId = Me.UserId
  158. Me.webOperationContext.OutgoingResponse.Headers.Add("Cache-Control", "no-cache")
  159. Dim userEndpoint = Me.pushUserEndpointsRepository.GetPushUserByApplicationAndDevice(applicationId, deviceId)
  160. Try
  161. Dim queueName = GetQueueName(applicationId, deviceId, userEndpoint.UserId)
  162. Dim queue = Me.cloudQueueClient.GetQueueReference(queueName)
  163. Dim messages = New List(Of String)()
  164. If queue.Exists() Then
  165. Dim message = queue.GetMessage()
  166. Do While message IsNot Nothing
  167. messages.Add(message.AsString)
  168. queue.DeleteMessage(message)
  169. message = queue.GetMessage()
  170. Loop
  171. End If
  172. Me.ResetTileNotificationCount(applicationId, deviceId)
  173. Return messages.ToArray()
  174. Catch exception As Exception
  175. Throw New WebFaultException(Of String)(String.Format(CultureInfo.InvariantCulture, "There was an error getting the push notification updates: {0}", exception.Message), HttpStatusCode.InternalServerError)
  176. End Try
  177. End Function
  178. Private Shared Function GetQueueName(ByVal applicationId As String, ByVal deviceId As String, ByVal userId As String) As String
  179. Dim uniqueName = String.Concat(applicationId, deviceId, userId)
  180. Return String.Concat("notification", uniqueName.GetHashCode())
  181. End Function
  182. Private Shared Function GetStorageAccountFromConfigurationSetting() As CloudStorageAccount
  183. Dim account As CloudStorageAccount = Nothing
  184. Try
  185. account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString")
  186. Catch e1 As InvalidOperationException
  187. account = Nothing
  188. End Try
  189. Return account
  190. End Function
  191. Private Sub ResetTileNotificationCount(ByVal applicationId As String, ByVal deviceId As String)
  192. Dim pushUserEndpoint = Me.pushUserEndpointsRepository.GetPushUserByApplicationAndDevice(applicationId, deviceId)
  193. pushUserEndpoint.TileCount = 0
  194. Dim tile = New TilePushNotificationMessage With {.SendPriority = MessageSendPriority.High, .Count = pushUserEndpoint.TileCount}
  195. ' Send a new tile notification message to reset the count in the phone application.
  196. tile.SendAndHandleErrors(New Uri(pushUserEndpoint.ChannelUri))
  197. ' Save the updated count.
  198. Me.pushUserEndpointsRepository.UpdatePushUserEndpoint(pushUserEndpoint)
  199. End Sub
  200. End Class
  201. End Namespace