public void NotificationInstallation_Serialization_IsConsistent() { // Arrange NotificationTemplate testSecondaryTemplate = new NotificationTemplate { Body = "mySecondaryBody", Headers = new Dictionary<string, string>() }; testSecondaryTemplate.Headers["mySecondaryHeaderName"] = "mySecondaryHeaderValue"; NotificationSecondaryTile testSecondaryTile = new NotificationSecondaryTile { PushChannel = "myPushChannel", Tags = new List<string>(), Templates = new Dictionary<string, NotificationTemplate>() }; testSecondaryTile.Tags.Add("myTag"); testSecondaryTile.Templates["mySecondaryTemplateName"] = testSecondaryTemplate; NotificationInstallation installation = new NotificationInstallation { PushChannel = "myPushChannel", Platform = "myPlatform", InstallationId = "myId", SecondaryTiles = new Dictionary<string, NotificationSecondaryTile>(), Templates = new Dictionary<string, NotificationTemplate>() }; installation.SecondaryTiles["myTestTile"] = testSecondaryTile; NotificationTemplate testTemplate = new NotificationTemplate { Body = "myBody", Headers = new Dictionary<string, string>() }; testSecondaryTemplate.Headers["myHeaderName"] = "myHeaderValue"; installation.Templates["myTemplateName"] = testTemplate; // Assert SerializationAssert.VerifySerialization(installation, "{\"pushChannel\":\"myPushChannel\",\"platform\":\"myPlatform\",\"installationId\":\"myId\",\"templates\":{\"myTemplateName\":{\"body\":\"myBody\",\"headers\":{},\"tags\":[]}},\"secondaryTiles\":{\"myTestTile\":{\"pushChannel\":\"myPushChannel\",\"tags\":[\"myTag\"],\"templates\":{\"mySecondaryTemplateName\":{\"body\":\"mySecondaryBody\",\"headers\":{\"mySecondaryHeaderName\":\"mySecondaryHeaderValue\",\"myHeaderName\":\"myHeaderValue\"},\"tags\":[]}}}},\"tags\":[]}"); }
/// <summary> /// Enables the registration of a device installation for push notifications via PUT request. /// If the specified installationId does not exist on the notification hub, a new installation is created and registered. /// If the specified installationId already exists, the installation is modified. /// </summary> /// <param name="installationId">The installation id to register or modify.</param> /// <param name="notificationInstallation">The <see cref="NotificationInstallation"/> object to register.</param> /// <returns><see cref="HttpResponseMessage"/> describing the result of the operation.</returns> public async Task<HttpResponseMessage> PutInstallation(string installationId, NotificationInstallation notificationInstallation) { if (!ModelState.IsValid) { throw new HttpResponseException(this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState)); } this.ValidateInstallationId(installationId); this.ValidateNotificationInstallation(installationId, notificationInstallation); ITraceWriter traceWriter = this.Configuration.Services.GetTraceWriter(); // The installation object that will be sent to NH. Installation installation = this.CreateInstallation(notificationInstallation); HashSet<string> tagsAssociatedWithInstallationId = await this.GetTagsAssociatedWithInstallationId(notificationInstallation.InstallationId); ClaimsPrincipal serviceUser = this.User as ClaimsPrincipal; if (tagsAssociatedWithInstallationId.Count == 0) { // Installation does not exist on NH. Add it. if (installation.Tags == null) { installation.Tags = new List<string>(); } // Tag the installation with the UserId if authenticated. if (serviceUser != null && serviceUser.Identity.IsAuthenticated) { Claim userIdClaim = serviceUser.FindFirst(ClaimTypes.NameIdentifier); if (userIdClaim != null) { string incomingUserTag = string.Format(UserIdTagPlaceholder, userIdClaim.Value); installation.Tags.Add(incomingUserTag); } } try { await this.UpsertInstallationAsync(installation); } catch (HttpResponseException) { throw; } catch (Exception ex) { string error = RResources.NotificationHub_CreateOrUpdateInstallationFailed.FormatForUser(installationId, ex.Message); traceWriter.Error(error, ex, this.Request, ServiceLogCategories.NotificationControllers); traceWriter.Error(error, ex, this.Request, LogCategories.NotificationControllers); // We return 4xx status code on error as it is impossible to know whether it is bad input or a // server error from NH. As a result we err on the bad request side. return this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex.Message); } } else { // Installation already existed on NH. if (serviceUser != null && serviceUser.Identity.IsAuthenticated) { // Because the user is authenticated, copy all previous tags except UserId. CopyTagsToInstallation(installation, tagsAssociatedWithInstallationId, false); // Add the incoming UserId. Claim userIdClaim = serviceUser.FindFirst(ClaimTypes.NameIdentifier); if (userIdClaim != null) { string incomingUserTag = string.Format(UserIdTagPlaceholder, userIdClaim.Value); AddTagToInstallation(installation, incomingUserTag); } } else { // Because the request is anonymous, copy all previous tags to the installation object, including the previous user tag. CopyTagsToInstallation(installation, tagsAssociatedWithInstallationId, true); } try { await this.UpsertInstallationAsync(installation); } catch (HttpResponseException) { throw; } catch (Exception ex) { string error = RResources.NotificationHub_CreateOrUpdateInstallationFailed.FormatForUser(installationId, ex.Message); traceWriter.Error(error, ex, this.Request, ServiceLogCategories.NotificationControllers); traceWriter.Error(error, ex, this.Request, LogCategories.NotificationControllers); // We return 4xx status code on error as it is impossible to know whether it is bad input or a // server error from NH. As a result we err on the bad request side. return this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex.Message); } } return this.Request.CreateResponse(HttpStatusCode.OK); }
internal void ValidateNotificationInstallation(string installationId, NotificationInstallation notificationInstallation) { if (notificationInstallation == null) { throw new HttpResponseException(this.Request.CreateBadRequestResponse(RResources.NotificationHub_NotificationInstallationWasNull.FormatForUser())); } if (notificationInstallation.InstallationId != null && !installationId.ToString().Equals(notificationInstallation.InstallationId, StringComparison.OrdinalIgnoreCase)) { throw new HttpResponseException(this.Request.CreateBadRequestResponse(RResources.NotificationHub_InstallationIdDoesntMatchUri.FormatForUser())); } // Store the installation id into NotificationInstallation object. notificationInstallation.InstallationId = installationId.ToString(); // Check the required fields of the NotificationInstallation object. If failed, return Bad Request. if (string.IsNullOrEmpty(notificationInstallation.PushChannel)) { throw new HttpResponseException(this.Request.CreateBadRequestResponse(RResources.NotificationHub_MissingPropertyInRequestBody.FormatForUser("pushChannel"))); } if (string.IsNullOrEmpty(notificationInstallation.Platform)) { throw new HttpResponseException(this.Request.CreateBadRequestResponse(RResources.NotificationHub_MissingPropertyInRequestBody.FormatForUser("platform"))); } if (string.Equals(notificationInstallation.Platform, WindowsStorePlatform, StringComparison.OrdinalIgnoreCase)) { if (notificationInstallation.SecondaryTiles != null) { this.ValidateSecondaryTiles(notificationInstallation); } } foreach (NotificationTemplate template in notificationInstallation.Templates.Values) { this.ValidateTemplate(template, notificationInstallation.Platform); } }
internal void ValidateSecondaryTiles(NotificationInstallation notificationInstallation) { if (notificationInstallation == null) { throw new HttpResponseException(this.Request.CreateBadRequestResponse(RResources.NotificationHub_NotificationInstallationWasNull.FormatForUser())); } foreach (NotificationSecondaryTile secondaryTile in notificationInstallation.SecondaryTiles.Values) { if (secondaryTile == null) { throw new HttpResponseException(this.Request.CreateBadRequestResponse(RResources.NotificationHub_SecondaryTileWasNull.FormatForUser())); } this.ValidateSecondaryTile(secondaryTile); } }
internal Installation CreateInstallation(NotificationInstallation notificationInstallation) { if (notificationInstallation == null) { throw new ArgumentNullException("notificationInstallation"); } if (notificationInstallation.Platform == null) { throw new ArgumentException("notificationInstallation.Platform is null"); } Installation installation = new Installation(); installation.InstallationId = notificationInstallation.InstallationId; installation.PushChannel = notificationInstallation.PushChannel; // Set the Platform. Create and add WnsSecondaryTile objects to the installation if WNS. if (notificationInstallation.Platform.Equals(WindowsStorePlatform, StringComparison.OrdinalIgnoreCase)) { installation.Platform = NotificationPlatform.Wns; // Parse each Secondary Tile passed in request and add to installation object. foreach (string tileName in notificationInstallation.SecondaryTiles.Keys) { NotificationSecondaryTile notificationTile = notificationInstallation.SecondaryTiles[tileName]; if (installation.SecondaryTiles == null) { installation.SecondaryTiles = new Dictionary<string, WnsSecondaryTile>(); } installation.SecondaryTiles[tileName] = CreateWnsSecondaryTile(notificationTile); } } else if (notificationInstallation.Platform.Equals(ApplePlatform, StringComparison.OrdinalIgnoreCase)) { installation.Platform = NotificationPlatform.Apns; } else if (notificationInstallation.Platform.Equals(GooglePlatform, StringComparison.OrdinalIgnoreCase)) { installation.Platform = NotificationPlatform.Gcm; } else { throw new HttpResponseException(this.Request.CreateBadRequestResponse(RResources.NotificationHub_UnsupportedPlatform.FormatForUser(notificationInstallation.Platform))); } // Create and add InstallationTemplate objects to the installation. foreach (string templateName in notificationInstallation.Templates.Keys) { NotificationTemplate template = notificationInstallation.Templates[templateName]; if (installation.Templates == null) { installation.Templates = new Dictionary<string, InstallationTemplate>(); } installation.Templates[templateName] = CreateInstallationTemplate(template, installation.Platform); } return installation; }
public void CreateInstallationObject_ParsingIsConsistent(string pushChannel, string platformAsString, NotificationPlatform platformAsEnum) { string installationId = "12345678-1234-1234-1234-123456789012"; string tileName = "myTile"; string tileTemplateName = "templateNameTile"; string tileTemplateBody = "myTemplateBodyTile"; string tileTemplateHeaderName = "templateHeaderNameTile"; string tileTemplateHeaderValue = "templateHeaderValueTile"; string installationTemplateName = "installationTemplateName"; string installationTemplateBody = "installationTemplateBody"; string installationTemplateHeaderName = "installationTemplateHeaderName"; string installationTemplateHeaderValue = "installationTemplateHeaderBody"; // Arrange Dictionary<string, string> tileTemplateHeaders = new Dictionary<string, string>(); tileTemplateHeaders[tileTemplateHeaderName] = tileTemplateHeaderValue; Dictionary<string, NotificationTemplate> tileTemplates = new Dictionary<string, NotificationTemplate>(); tileTemplates[tileTemplateName] = new NotificationTemplate { Body = tileTemplateBody, Headers = tileTemplateHeaders }; Dictionary<string, NotificationSecondaryTile> tiles = new Dictionary<string, NotificationSecondaryTile>(); tiles[tileName] = new NotificationSecondaryTile { PushChannel = pushChannel, Tags = new List<string> { "tag1", "tag2" }, Templates = tileTemplates }; Dictionary<string, string> installationTemplateHeaders = new Dictionary<string, string>(); installationTemplateHeaders[installationTemplateHeaderName] = installationTemplateHeaderValue; Dictionary<string, NotificationTemplate> installationTemplates = new Dictionary<string, NotificationTemplate>(); installationTemplates[installationTemplateName] = new NotificationTemplate { Body = installationTemplateBody, Headers = installationTemplateHeaders }; NotificationInstallation notificationInstallation = new NotificationInstallation { Platform = platformAsString, PushChannel = pushChannel, SecondaryTiles = tiles, Tags = new List<string> { "tagA", "tagB" }, Templates = installationTemplates }; notificationInstallation.InstallationId = installationId; NotificationInstallationsControllerMock mock = new NotificationInstallationsControllerMock(); // Act Installation testInstallation = mock.CreateInstallation(notificationInstallation); // Assert Assert.NotNull(testInstallation); Assert.Equal(installationId, testInstallation.InstallationId); Assert.Equal(platformAsEnum, testInstallation.Platform); Assert.Equal(pushChannel, testInstallation.PushChannel); if (platformAsEnum == NotificationPlatform.Wns) { Assert.NotNull(testInstallation.SecondaryTiles); Assert.NotNull(testInstallation.SecondaryTiles[tileName]); Assert.Equal(pushChannel, testInstallation.SecondaryTiles[tileName].PushChannel); Assert.Equal(0, testInstallation.SecondaryTiles[tileName].Tags.Count); Assert.NotNull(testInstallation.SecondaryTiles[tileName].Templates); Assert.NotNull(testInstallation.SecondaryTiles[tileName].Templates[tileTemplateName]); // Tags were stripped within the tile Assert.Equal(tileTemplateBody, testInstallation.SecondaryTiles[tileName].Templates[tileTemplateName].Body); Assert.Equal(installationTemplateHeaderValue, testInstallation.Templates[installationTemplateName].Headers[installationTemplateHeaderName]); } else { Assert.Null(testInstallation.SecondaryTiles); Assert.Null(testInstallation.Templates[installationTemplateName].Headers); } Assert.NotNull(testInstallation.Templates[installationTemplateName]); Assert.Equal(installationTemplateBody, testInstallation.Templates[installationTemplateName].Body); // Tags were stripped within the template Assert.Equal(0, testInstallation.Templates[installationTemplateName].Tags.Count); }