### Install via Package Managers Source: https://github.com/easyabp/notificationservice/blob/master/host/EasyAbp.NotificationService.Web.Host/wwwroot/libs/malihu-custom-scrollbar-plugin/readme.md Commands to install the plugin using npm or Bower. ```shell npm install malihu-custom-scrollbar-plugin ``` ```shell bower install malihu-custom-scrollbar-plugin ``` -------------------------------- ### CreateAsync Usage Example Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/notification-managers.md Example demonstrating how to use CreateNotificationsAsync within a CreateAsync method. It initializes NotificationInfo and populates its properties. ```csharp public override async Task<(List, NotificationInfo)> CreateAsync( CreateNotificationInfoModel model) { var notificationInfo = new NotificationInfo(GuidGenerator.Create(), CurrentTenant.Id); // Populates Subject and Body custom properties notificationInfo.SetMailingData(model.GetSubject(), model.GetBody()); var notifications = await CreateNotificationsAsync(notificationInfo, model); return (notifications, notificationInfo); } ``` -------------------------------- ### Configure with Webpack Source: https://github.com/easyabp/notificationservice/blob/master/host/EasyAbp.NotificationService.Web.Host/wwwroot/libs/malihu-custom-scrollbar-plugin/readme.md Setup requirements and configuration for using the plugin with Webpack, including necessary loaders. ```shell npm install imports-loader npm install jquery-mousewheel npm install malihu-custom-scrollbar-plugin ``` ```javascript module.exports = { module: { loaders: [ { test: /jquery-mousewheel/, loader: "imports?define=>false&this=>window" }, { test: /malihu-custom-scrollbar-plugin/, loader: "imports?define=>false&this=>window" } ] } }; var $ = require('jquery'); require("jquery-mousewheel")($); require('malihu-custom-scrollbar-plugin')($); ``` -------------------------------- ### Usage Example for CreateAsync Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/notification-app-services.md Demonstrates how to use the CreateAsync method to create and queue email notifications. The actual delivery occurs asynchronously in the background. ```csharp var model = new CreateEmailNotificationEto( tenantId: Guid.Parse("12345678-1234-1234-1234-123456789012"), userIds: new[] { userId1, userId2 }, subject: "Order confirmation", body: "

Your order has been placed

"); var result = await notificationIntegrationService.CreateAsync(model); // Notifications are now queued; delivery happens in background foreach (var notificationDto in result.Items) { Console.WriteLine($"Created notification {notificationDto.Id}, status: {notificationDto.Success}"); } ``` -------------------------------- ### Get Failed Notifications Example Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/types.md Demonstrates how to retrieve a list of failed notifications for a specific user, including pagination and sorting. ```csharp // Get failed notifications for a user var input = new NotificationGetListInput { UserId = userId, Success = false, SkipCount = 0, MaxResultCount = 20, Sorting = "CreationTime desc" }; var result = await notificationAppService.GetListAsync(input); ``` -------------------------------- ### CreatePrivateMessageNotificationEto Usage Example Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/private-messaging-provider.md Demonstrates how to instantiate CreatePrivateMessageNotificationEto with a list of users, tenant ID, title, content, and sender information. ```csharp var users = new[] { new NotificationUserInfoModel(userId1, "alice"), new NotificationUserInfoModel(userId2, "bob") }; var eto = new CreatePrivateMessageNotificationEto( tenantId: currentTenant.Id, users: users, title: "Team Announcement", content: "Welcome to the team!", sendFromCreator: true); ``` -------------------------------- ### cURL Example for Immediate Notifications Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/endpoints.md This cURL command shows how to use the quick-send endpoint for immediate, synchronous notification delivery. ```bash curl -X POST "https://api.example.com/integration-api/notification-service/notification/quick-send" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \ -d '{ "notificationMethod": "Mailing", "userIds": ["223e4567-e89b-12d3-a456-426614174001"], "tenantId": "123e4567-e89b-12d3-a456-426614174000", "subject": "Password Reset", "body": "

Click here to reset your password

" }' ``` -------------------------------- ### QuickSendAsync Method Usage Example Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/notification-app-services.md Demonstrates how to use the QuickSendAsync method to create and send email notifications. Includes error handling for failed sends and general exceptions. ```csharp var model = new CreateEmailNotificationEto( tenantId: currentTenant.Id, userIds: new[] { userId }, subject: "Password reset", body: "

Click here to reset your password

"); try { var result = await notificationIntegrationService.QuickSendAsync(model); foreach (var dto in result.Items) { if (dto.Success.HasValue && !dto.Success.Value) { Console.WriteLine($"Failed: {dto.FailureReason}"); } } } catch (Exception ex) { Console.WriteLine($"Error during quick send: {ex.Message}"); } ``` -------------------------------- ### Get All SMS Notifications Example Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/types.md Shows how to filter and retrieve all notifications sent via the SMS method, with specified pagination. ```csharp // Get all SMS notifications input = new NotificationGetListInput { NotificationMethod = "Sms", SkipCount = 0, MaxResultCount = 50 }; ``` -------------------------------- ### Create Notification Instance Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/notification-domain-classes.md Example of creating a Notification object using its constructor. This demonstrates how to provide all required parameters for a new notification. ```csharp var notification = new Notification( id: Guid.NewGuid(), tenantId: currentTenant.Id, userId: userId, userName: "john.doe", notificationInfoId: notificationInfoId, notificationMethod: "Mailing" ); ``` -------------------------------- ### EmailNotificationManager Usage Example Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/mailing-provider.md Example of how to use the EmailNotificationManager to create and send email notifications. ```csharp var manager = serviceProvider.GetRequiredService(); var model = new CreateEmailNotificationEto( tenantId: currentTenant.Id, userIds: new[] { userId }, subject: "Welcome", body: "

Welcome

"); var (notifications, info) = await manager.CreateAsync(model); ``` -------------------------------- ### Get Retries for a Specific Notification Example Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/types.md Illustrates how to query for retry attempts of a particular notification, specifying pagination. ```csharp // Get retries for a specific notification input = new NotificationGetListInput { RetryForNotificationId = originalNotificationId, SkipCount = 0, MaxResultCount = 10 }; ``` -------------------------------- ### Notification Domain Service Usage Example Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/repositories-and-infrastructure.md Demonstrates how to use the INotificationRepository within a domain service for persisting, retrieving, and updating notifications. ```csharp public class NotificationDomainService { private readonly INotificationRepository _repository; public NotificationDomainService(INotificationRepository repository) { _repository = repository; } public async Task PersistNotificationsAsync(List notifications) { foreach (var notification in notifications) { await _repository.InsertAsync(notification, autoSave: true); } } public async Task GetNotificationAsync(Guid id) { return await _repository.GetAsync(id); } public async Task UpdateNotificationAsync(Notification notification) { await _repository.UpdateAsync(notification, autoSave: true); } } ``` -------------------------------- ### Install malihu custom scrollbar plugin via npm Source: https://github.com/easyabp/notificationservice/blob/master/host/EasyAbp.NotificationService.IdentityServer/wwwroot/libs/malihu-custom-scrollbar-plugin/readme.md Use npm to install the malihu custom scrollbar plugin. This is the recommended method for Node.js projects. ```bash npm install malihu-custom-scrollbar-plugin ``` -------------------------------- ### Appsettings.json for Notification Service Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/configuration.md Example appsettings.json configuration for the Notification Service, including database connection string and enabling background jobs. ```json { "ConnectionStrings": { "Default": "Server=localhost;Database=MyDb;Integrated Security=true;" }, "Abp": { "BackgroundJobs": { "IsJobExecutionEnabled": true } } } ``` -------------------------------- ### Usage Example for OtpVerificationSmsFactory Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/sms-provider.md Demonstrates how to obtain an instance of OtpVerificationSmsFactory and use it to send an OTP verification SMS. Includes checking the success status of the sent SMS. ```csharp var factory = serviceProvider.GetRequiredService(); var model = new OtpVerificationModel { Code = "123456", ExpiryMinutes = 5 }; // Send SMS immediately var eto = await factory.CreateAsync(model, userId); var results = await notificationIntegrationService.QuickSendAsync(eto); if (results.Items.First().Success.HasValue && results.Items.First().Success.Value) { Console.WriteLine("SMS sent successfully"); } else { Console.WriteLine($"SMS failed: {results.Items.First().FailureReason}"); } ``` -------------------------------- ### Implement Custom Notification Service Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/repositories-and-infrastructure.md Example of a custom notification service that extends NotificationServiceAppService. It demonstrates how to inject and use a repository to query notification data. ```csharp public class CustomNotificationService : NotificationServiceAppService { private readonly INotificationRepository _repository; public CustomNotificationService(INotificationRepository repository) { _repository = repository; } public async Task GetFailedNotificationCountAsync(Guid userId) { var count = (await _repository.GetListAsync(x => x.UserId == userId && x.Success == false )).Count; return count; } } ``` -------------------------------- ### cURL Example for Queued Notifications Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/endpoints.md This cURL command demonstrates how to send a POST request to the notification creation endpoint for queued sending. ```bash curl -X POST "https://api.example.com/integration-api/notification-service/notification" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \ -d '{ "notificationMethod": "Mailing", "userIds": ["223e4567-e89b-12d3-a456-426614174001"], "tenantId": "123e4567-e89b-12d3-a456-426614174000", "subject": "Welcome", "body": "

Hello and welcome!

" }' ``` -------------------------------- ### Configure Notification Service Permissions in a Module Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/configuration.md Example of how to define and configure Notification Service permissions within a module's permission definition provider. ```csharp public class MyPermissionDefinitionProvider : PermissionDefinitionProvider { public override void Define(IPermissionDefinitionContext context) { var myGroup = context.AddGroup("MyApp"); var notificationGroup = context.AddGroup( NotificationServicePermissions.GroupName); var notificationPermission = notificationGroup.AddPermission( NotificationServicePermissions.Notification.Default); notificationPermission.AddChild( NotificationServicePermissions.Notification.Manage); } } ``` -------------------------------- ### Usage Example: Querying Notification List in C# Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/types.md Demonstrates how to create an input DTO for querying notifications, call the notification application service, and iterate through the results to display notification details. Handles different notification statuses and failure reasons. ```csharp var input = new NotificationGetListInput { UserId = userId, NotificationMethod = "Mailing", Success = false, SkipCount = 0, MaxResultCount = 10 }; var result = await notificationAppService.GetListAsync(input); foreach (var dto in result.Items) { Console.WriteLine($"Notification {dto.Id}:"); Console.WriteLine($" User: {dto.UserName}"); Console.WriteLine($" Method: {dto.NotificationMethod}"); Console.WriteLine($" Status: {(dto.Success.HasValue ? (dto.Success.Value ? "Sent" : "Failed") : "Pending")}"); if (!dto.Success.GetValueOrDefault()) { Console.WriteLine($" Reason: {dto.FailureReason}"); } } ``` -------------------------------- ### Implement Email Notification Creation Event Handler Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/notification-managers.md An example implementation of NotificationCreationEventHandlerBase for handling 'Mailing' notification events. It triggers a background job for sending emails. ```csharp public class EmailNotificationCreationEventHandler : NotificationCreationEventHandlerBase { protected override string NotificationMethod => "Mailing"; protected override async Task InternalHandleEventAsync(EntityCreatedEventData eventData) { var notification = eventData.Entity; // Trigger background job or send immediately await backgroundJobManager.EnqueueAsync( new EmailSendingJobArgs { NotificationId = notification.Id }); } ``` -------------------------------- ### Usage Example of INotificationInfoRepository in a Service Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/repositories-and-infrastructure.md Demonstrates how to inject and use the INotificationInfoRepository within a service class to perform operations like creating and retrieving NotificationInfo entities. ```csharp public class NotificationInfoService { private readonly INotificationInfoRepository _repository; public NotificationInfoService(INotificationInfoRepository repository) { _repository = repository; } public async Task CreateNotificationInfoAsync( Guid id, Guid? tenantId, Dictionary data) { var info = new NotificationInfo(id, tenantId, data); await _repository.InsertAsync(info, autoSave: true); } public async Task GetNotificationInfoAsync(Guid id) { return await _repository.GetAsync(id); } } ``` -------------------------------- ### Complete Email Notification Flow Example Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/mailing-provider.md This snippet shows how to create a custom notification factory for order confirmation emails and then use it to send notifications. It covers both background sending via an event bus and immediate sending. ```csharp // 1. Create factory public class OrderConfirmationEmailFactory : NotificationFactory, ITransientDependency { public override async Task CreateAsync( OrderConfirmationModel model, IEnumerable userIds) { var subject = $"Order #{model.OrderId} Confirmation"; var body = $"\n

Thank you for your order

\n

Order ID: {model.OrderId}

\n

Total: ${model.Total}

"; return new CreateEmailNotificationEto( tenantId: CurrentTenant.Id, userIds: userIds, subject: subject, body: body); } public override async Task CreateAsync( OrderConfirmationModel model, IEnumerable users) { var subject = $"Order #{model.OrderId} Confirmation"; var body = $"

Thank you for your order

"; return new CreateEmailNotificationEto( tenantId: CurrentTenant.Id, users: users, subject: subject, body: body); } } // 2. Use factory to send var factory = serviceProvider.GetRequiredService(); var model = new OrderConfirmationModel { OrderId = 12345, Total = 99.99m }; // Option 1: Background sending var eto = await factory.CreateAsync(model, customerId); await distributedEventBus.PublishAsync(eto); // Option 2: Quick send (immediate) var eto = await factory.CreateAsync(model, customerId); var results = await notificationIntegrationService.QuickSendAsync(eto); ``` -------------------------------- ### Custom Implementation of ExternalUserLookupServiceProvider Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/repositories-and-infrastructure.md Provides a custom implementation of `IExternalUserLookupServiceProvider` that retrieves user data from a repository. This example maps repository user properties to the `IUserData` interface. ```csharp public class CustomUserLookupProvider : IExternalUserLookupServiceProvider, ITransientDependency { private readonly IRepository _userRepository; public async Task FindByIdAsync(Guid id) { var user = await _userRepository.FindAsync(id); if (user == null) return null; return new UserData { Id = user.Id, UserName = user.UserName, Email = user.Email, PhoneNumber = user.PhoneNumber, Name = user.FirstName, Surname = user.LastName }; } } ``` -------------------------------- ### Complete Notification Module Configuration Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/configuration.md A comprehensive example of an ABP module class configuring various notification providers (Email, SMS), MailKit SMTP settings, and custom services. Ensure to include necessary dependencies like NotificationServiceApplicationModule and provider-specific modules. ```csharp [DependsOn( typeof(NotificationServiceApplicationModule), typeof(NotificationServiceEntityFrameworkCoreModule), typeof(NotificationServiceHttpApiModule), typeof(NotificationServiceProviderMailingModule), typeof(NotificationServiceProviderSmsModule) )] public class MyNotificationModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { // Configure providers Configure(options => { // Email options.Providers.AddProvider( new NotificationServiceProviderConfiguration( NotificationProviderMailingConsts.NotificationMethod, typeof(EmailNotificationManager))); // SMS options.Providers.AddProvider( new NotificationServiceProviderConfiguration( NotificationProviderSmsConsts.NotificationMethod, typeof(CustomSmsNotificationManager))); }); // Configure email Configure(options => { options.Host = "smtp.gmail.com"; options.Port = 587; options.UserName = "noreply@example.com"; options.Password = Environment.GetEnvironmentVariable("SMTP_PASSWORD"); options.EnableSslTls = true; }); // Register custom providers context.Services.AddTransient(); context.Services.AddTransient(); } } ``` -------------------------------- ### Custom User Email Address Provider Implementation Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/mailing-provider.md An example of a custom implementation for IUserEmailAddressProvider. This provider retrieves email addresses from ABP Identity users using the IRepository. ```csharp public class CustomUserEmailAddressProvider : IUserEmailAddressProvider, ITransientDependency { private readonly IRepository _userRepository; public CustomUserEmailAddressProvider(IRepository userRepository) { _userRepository = userRepository; } public async Task GetAsync(Guid userId) { var user = await _userRepository.FindAsync(userId); return user?.Email; } } ``` -------------------------------- ### Initialize with Browserify Source: https://github.com/easyabp/notificationservice/blob/master/host/EasyAbp.NotificationService.Web.Host/wwwroot/libs/malihu-custom-scrollbar-plugin/readme.md Usage pattern for integrating the plugin within a Browserify environment. ```javascript var $ = require('jquery'); require('malihu-custom-scrollbar-plugin')($); ``` -------------------------------- ### Create Welcome Email Factory Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/README.md Implement a notification factory for creating welcome emails, handling different user input types and generating the email content. ```csharp public class WelcomeEmailFactory : NotificationFactory, ITransientDependency { public override async Task CreateAsync( WelcomeModel model, IEnumerable userIds) { return new CreateEmailNotificationEto( tenantId: CurrentTenant.Id, userIds: userIds, subject: "Welcome!", body: $"

Hello {model.UserName}

"); } public override async Task CreateAsync( WelcomeModel model, IEnumerable users) { return new CreateEmailNotificationEto( tenantId: CurrentTenant.Id, users: users, subject: "Welcome!", body: $"

Hello

"); } } ``` -------------------------------- ### Install malihu custom scrollbar plugin via Bower Source: https://github.com/easyabp/notificationservice/blob/master/host/EasyAbp.NotificationService.IdentityServer/wwwroot/libs/malihu-custom-scrollbar-plugin/readme.md Use Bower to install the malihu custom scrollbar plugin. This is suitable for projects managed with Bower. ```bash bower install malihu-custom-scrollbar-plugin ``` -------------------------------- ### Create and Apply EF Core Migrations Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/configuration.md Use the .NET CLI to add a new migration for the Notification Service and then apply it to your database. ```bash dotnet ef migrations add AddNotificationService dotnet ef database update ``` -------------------------------- ### SetNotificationResultAsync Usage Example Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/notification-managers.md Example demonstrating how to use SetNotificationResultAsync within a try-catch block to record the outcome of sending an email. It records success on completion and failure with the exception message on error. ```csharp try { await SendEmailAsync(userEmail, subject, body); await SetNotificationResultAsync(notification, true); } catch (Exception ex) { await SetNotificationResultAsync(notification, false, ex.Message); } ``` -------------------------------- ### Get Notification Info List Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/MANIFEST.md Retrieves a list of notification information. ```APIDOC ## GET /api/notification-service/notification-info ### Description Retrieves a list of notification information. ### Method GET ### Endpoint /api/notification-service/notification-info ``` -------------------------------- ### Configure Notification Module Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/README.md Set up the basic module with dependencies and configure notification service options, including adding an email provider. ```csharp [DependsOn( typeof(NotificationServiceApplicationModule), typeof(NotificationServiceEntityFrameworkCoreModule), typeof(NotificationServiceHttpApiModule), typeof(NotificationServiceProviderMailingModule) )] public class MyNotificationModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { Configure(options => { options.Providers.AddProvider( new NotificationServiceProviderConfiguration( NotificationProviderMailingConsts.NotificationMethod, typeof(EmailNotificationManager))); }); } } ``` -------------------------------- ### GetCategory Extension Method Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/private-messaging-provider.md Gets the message category from custom properties on CreatePrivateMessageNotificationEto. ```csharp public static string GetCategory(this CreatePrivateMessageNotificationEto eto) ``` -------------------------------- ### GetContent Extension Method Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/private-messaging-provider.md Gets the message content from custom properties on CreatePrivateMessageNotificationEto. ```csharp public static string GetContent(this CreatePrivateMessageNotificationEto eto) ``` -------------------------------- ### Initialize NotificationInfo Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/notification-domain-classes.md Use this constructor to create a new NotificationInfo instance with a unique ID and an optional tenant ID. ```csharp var notificationInfo = new NotificationInfo( id: Guid.NewGuid(), tenantId: currentTenant.Id ); ``` -------------------------------- ### GetTitle Extension Method Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/private-messaging-provider.md Gets the message title from custom properties on CreatePrivateMessageNotificationEto. ```csharp public static string GetTitle(this CreatePrivateMessageNotificationEto eto) ``` -------------------------------- ### Get Notification by ID Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/MANIFEST.md Retrieves a specific notification using its unique identifier. ```APIDOC ## GET /api/notification-service/notification/{id} ### Description Retrieves a specific notification by its ID. ### Method GET ### Endpoint /api/notification-service/notification/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the notification. ``` -------------------------------- ### Use Notification Factory to Create and Publish Notifications Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/notification-factory.md Demonstrates three options for using the notification factory: publishing via event bus, queuing via integration service, or sending immediately. ```csharp var factory = serviceProvider.GetRequiredService(); var model = new UserWelcomeNotificationDataModel( userName: "john.doe", giftCardCode: "GIFT123"); // Option 1: Publish via event bus (background processing) var eto = await factory.CreateAsync(model, userId); await distributedEventBus.PublishAsync(eto); // Option 2: Create and queue via integration service (background) var eto = await factory.CreateAsync(model, userId); var notifications = await notificationIntegrationService.CreateAsync(eto); // Option 3: Create and send immediately var eto = await factory.CreateAsync(model, userId); var notifications = await notificationIntegrationService.QuickSendAsync(eto); ``` -------------------------------- ### GetSendFromCreator Extension Method Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/private-messaging-provider.md Gets the sender type flag from custom properties on CreatePrivateMessageNotificationEto. ```csharp public static bool GetSendFromCreator(this CreatePrivateMessageNotificationEto eto) ``` -------------------------------- ### Initialize NotificationInfo with Data Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/notification-domain-classes.md Use this constructor when you need to pre-populate the NotificationInfo with custom key-value data. ```csharp public NotificationInfo( Guid id, Guid? tenantId, Dictionary dataDictionary) ``` -------------------------------- ### Override IdentityUserEmailAddressProvider Source: https://github.com/easyabp/notificationservice/blob/master/docs/README.md Example of overriding the `IdentityUserEmailAddressProvider` to customize the source of user email addresses for notifications. ```csharp public class MyIdentityUserEmailAddressProvider : IdentityUserEmailAddressProvider { public override Task GetEmailAsync(IdentityUser user) { // Custom logic to get email address return base.GetEmailAsync(user); } } ``` -------------------------------- ### Catching and Handling KeyNotFoundException Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/errors.md Demonstrates how to catch KeyNotFoundException and handle it by logging an error and throwing a BusinessException with a specific code and message. ```csharp try { var manager = notificationManagerResolver.Resolve(notificationMethod); } catch (KeyNotFoundException ex) { logger.LogError($"Notification method '{notificationMethod}' is not registered"); throw new BusinessException( code: "UnknownNotificationMethod", message: $"Notification method '{notificationMethod}' is not configured"); } ``` -------------------------------- ### Get Notifications with Filters Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/MANIFEST.md Retrieves a list of notifications, allowing for filtering based on various criteria. ```APIDOC ## GET /api/notification-service/notification ### Description Retrieves a list of notifications with optional filtering capabilities. ### Method GET ### Endpoint /api/notification-service/notification ### Parameters #### Query Parameters - **filters** (object) - Optional - Criteria to filter the notifications. (Specific filter fields are not detailed in the source.) ``` -------------------------------- ### Override IdentityUserPhoneNumberProvider Source: https://github.com/easyabp/notificationservice/blob/master/docs/README.md Example of overriding the `IdentityUserPhoneNumberProvider` to customize the source of user phone numbers for SMS notifications. ```csharp public class MyIdentityUserPhoneNumberProvider : IdentityUserPhoneNumberProvider { public override Task GetPhoneNumberAsync(IdentityUser user) { // Custom logic to get phone number return base.GetPhoneNumberAsync(user); } } ``` -------------------------------- ### GET /api/notification-service/notification/{id} Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/endpoints.md Retrieves a single notification by its unique ID. Requires authentication and appropriate permissions. ```APIDOC ## GET /api/notification-service/notification/{id} ### Description Retrieves a single notification by ID. Requires authentication and appropriate permissions. ### Method GET ### Endpoint /api/notification-service/notification/{id} ### Parameters #### Path Parameters - **id** (Guid) - Required - Notification ID #### Request Headers - **Authorization** (string) - Required - Bearer ### Response #### Success Response (200) - **id** (Guid) - Notification ID - **userId** (Guid) - The ID of the user the notification is for - **userName** (string) - The name of the user the notification is for - **notificationInfoId** (Guid) - The ID of the associated notification info - **notificationMethod** (string) - The method used for notification (e.g., Mailing) - **success** (boolean) - Indicates if the notification was successfully delivered - **completionTime** (datetime) - The time the notification process was completed - **failureReason** (string) - The reason for failure, if applicable - **retryForNotificationId** (Guid) - The ID of the notification this is a retry for, if applicable - **creationTime** (datetime) - The time the notification was created - **creatorId** (Guid) - The ID of the user who created the notification #### Response Example ```json { "id": "123e4567-e89b-12d3-a456-426614174000", "userId": "223e4567-e89b-12d3-a456-426614174001", "userName": "john.doe", "notificationInfoId": "323e4567-e89b-12d3-a456-426614174002", "notificationMethod": "Mailing", "success": true, "completionTime": "2024-01-15T10:30:00", "failureReason": null, "retryForNotificationId": null, "creationTime": "2024-01-15T10:20:00", "creatorId": "423e4567-e89b-12d3-a456-426614174003" } ``` ### Error Handling - **401**: Unauthorized; authentication required - **403**: Forbidden; insufficient permissions - **404**: Notification not found ### Permission Required - `EasyAbp.NotificationService.Notification.Manage` ``` -------------------------------- ### Publish Notification using Factory and Event Bus Source: https://github.com/easyabp/notificationservice/blob/master/docs/README.md Demonstrates using a notification factory to create an ETO and then publishing it via the distributed event bus for background processing. Alternatively, use the `notificationIntegrationService` for immediate or background sending. ```csharp var eto = await userWelcomeNotificationFactory.CreateAsync( model: new UserWelcomeNotificationDataModel(userData.UserName, giftCardCode), userId: userData.Id ); // use the distributed event bus to create notifications and send them in the background await distributedEventBus.PublishAsync(eto); // or use the integration service to create notifications and send them in the background var notifications = await notificationIntegrationService.CreateAsync(eto); // or use the integration service to create notifications and send it them immediately var notifications = await notificationIntegrationService.QuickSendAsync(eto); ``` -------------------------------- ### Get Notification Info by ID Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/MANIFEST.md Retrieves detailed information about a specific notification using its unique identifier. ```APIDOC ## GET /api/notification-service/notification-info/{id} ### Description Retrieves detailed information for a specific notification by its ID. ### Method GET ### Endpoint /api/notification-service/notification-info/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the notification info. ``` -------------------------------- ### Get Mailing Body from NotificationInfo Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/mailing-provider.md Retrieves the email body that was previously stored as a custom property on the NotificationInfo object. ```csharp public static string GetMailingBody(this NotificationInfo notificationInfo) ``` -------------------------------- ### Configure Connection Strings Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/configuration.md Define connection strings for your application in `appsettings.json`. You can specify a dedicated connection string for Notification Service or rely on the default one. ```json { "ConnectionStrings": { "Default": "Server=localhost;Database=MyDb;...", "EasyAbpNotificationService": "Server=localhost;Database=MyDb;..." } } ``` ```json { "ConnectionStrings": { "Default": "Server=localhost;Database=MyDb;..." } } ``` -------------------------------- ### Get Mailing Subject from NotificationInfo Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/mailing-provider.md Retrieves the email subject that was previously stored as a custom property on the NotificationInfo object. ```csharp public static string GetMailingSubject(this NotificationInfo notificationInfo) ``` -------------------------------- ### Create Email Notification ETO with Tenant ID Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/README.md Demonstrates creating a `CreateEmailNotificationEto` object, explicitly setting the tenant ID for multi-tenancy awareness. ```csharp var eto = new CreateEmailNotificationEto( tenantId: currentTenant.Id, // Multi-tenant aware userIds: userIds, subject: "Hello", body: "

Content

"); ``` -------------------------------- ### Registering Notification Providers Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/errors.md Shows how to register notification providers like Email and SMS in the module configuration to prevent KeyNotFoundException. ```csharp public class MyNotificationModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { Configure(options => { // Register Email provider options.Providers.AddProvider( new NotificationServiceProviderConfiguration( NotificationProviderMailingConsts.NotificationMethod, typeof(EmailNotificationManager))); // Register SMS provider options.Providers.AddProvider( new NotificationServiceProviderConfiguration( NotificationProviderSmsConsts.NotificationMethod, typeof(SmsNotificationManager))); }); } } ``` -------------------------------- ### Get NotificationInfo List Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/endpoints.md Retrieves a paginated list of notification information records, with options for skipping, limiting results, and sorting. ```APIDOC ## GET /api/notification-service/notification-info ### Description Retrieves a paginated list of notification information records. ### Method GET ### Endpoint /api/notification-service/notification-info ### Parameters #### Query Parameters - **skipCount** (integer) - Optional - 0 - Number of records to skip - **maxResultCount** (integer) - Optional - 10 - Maximum records per page - **sorting** (string) - Optional - null - Sort expression ### Response #### Success Response (200) - **items** (array) - An array of notification information objects. - **id** (Guid) - NotificationInfo ID - **creationTime** (DateTime) - The creation time of the notification. - **creatorId** (Guid) - The ID of the user who created the notification. - **lastModificationTime** (DateTime) - The last modification time of the notification. - **lastModifierId** (Guid) - The ID of the user who last modified the notification. - **isDeleted** (Boolean) - Indicates if the notification has been deleted. - **deletionTime** (DateTime) - The time the notification was deleted. - **deleterId** (Guid) - The ID of the user who deleted the notification. - **totalCount** (integer) - The total number of records available. #### Response Example ```json { "items": [ { "id": "323e4567-e89b-12d3-a456-426614174002", "creationTime": "2024-01-15T10:20:00", "creatorId": "423e4567-e89b-12d3-a456-426614174003", "lastModificationTime": "2024-01-15T10:30:00", "lastModifierId": "423e4567-e89b-12d3-a456-426614174003", "isDeleted": false, "deletionTime": null, "deleterId": null } ], "totalCount": 500 } ``` ``` -------------------------------- ### Get NotificationInfo by ID Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/endpoints.md Retrieves a single notification information record using its unique ID. Requires the 'EasyAbp.NotificationService.Notification.Manage' permission. ```json { "id": "323e4567-e89b-12d3-a456-426614174002", "creationTime": "2024-01-15T10:20:00", "creatorId": "423e4567-e89b-12d3-a456-426614174003", "lastModificationTime": "2024-01-15T10:30:00", "lastModifierId": "423e4567-e89b-12d3-a456-426614174003", "isDeleted": false, "deletionTime": null, "deleterId": null } ``` -------------------------------- ### GET /api/notification-service/notification Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/endpoints.md Retrieves a paginated list of notifications, with options to filter by various criteria. Requires authentication and appropriate permissions. ```APIDOC ## GET /api/notification-service/notification ### Description Retrieves a paginated list of notifications with optional filters. Requires authentication and appropriate permissions. ### Method GET ### Endpoint /api/notification-service/notification ### Parameters #### Query Parameters - **userId** (Guid) - Optional - Filter by recipient user ID - **userName** (string) - Optional - Filter by user name (contains match) - **notificationInfoId** (Guid) - Optional - Filter by parent NotificationInfo ID - **notificationMethod** (string) - Optional - Filter by method name (contains match) - **success** (boolean) - Optional - Filter by delivery status - **creationTime** (datetime) - Optional - Filter by creation date - **creatorId** (Guid) - Optional - Filter by creator user ID - **completionTime** (datetime) - Optional - Filter by completion date - **failureReason** (string) - Optional - Filter by failure message (contains match) - **retryForNotificationId** (Guid) - Optional - Filter by original notification ID - **skipCount** (integer) - Optional - Default: 0 - Number of records to skip - **maxResultCount** (integer) - Optional - Default: 10 - Maximum records per page - **sorting** (string) - Optional - Sort expression (e.g., "CreationTime desc") #### Request Headers - **Authorization** (string) - Required - Bearer ### Response #### Success Response (200) - **items** (array) - List of notifications - **id** (Guid) - Notification ID - **userId** (Guid) - The ID of the user the notification is for - **userName** (string) - The name of the user the notification is for - **notificationInfoId** (Guid) - The ID of the associated notification info - **notificationMethod** (string) - The method used for notification (e.g., Mailing) - **success** (boolean) - Indicates if the notification was successfully delivered - **completionTime** (datetime) - The time the notification process was completed - **failureReason** (string) - The reason for failure, if applicable - **retryForNotificationId** (Guid) - The ID of the notification this is a retry for, if applicable - **creationTime** (datetime) - The time the notification was created - **creatorId** (Guid) - The ID of the user who created the notification - **totalCount** (integer) - Total number of notifications matching the filter #### Response Example ```json { "items": [ { "id": "123e4567-e89b-12d3-a456-426614174000", "userId": "223e4567-e89b-12d3-a456-426614174001", "userName": "john.doe", "notificationInfoId": "323e4567-e89b-12d3-a456-426614174002", "notificationMethod": "Mailing", "success": true, "completionTime": "2024-01-15T10:30:00", "failureReason": null, "retryForNotificationId": null, "creationTime": "2024-01-15T10:20:00", "creatorId": "423e4567-e89b-12d3-a456-426614174003" } ], "totalCount": 150 } ``` ### Error Handling - **400**: Bad request; invalid filter parameters - **401**: Unauthorized - **403**: Forbidden; insufficient permissions ### Permission Required - `EasyAbp.NotificationService.Notification.Manage` ``` -------------------------------- ### NotificationCreationEventHandlerBase.InternalHandleEventAsync Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/notification-managers.md Protected abstract method to be overridden for implementing sending logic. Called only when the notification method matches and delivery has not started. ```APIDOC ## InternalHandleEventAsync Method ### Description Override to implement sending logic. Called only when the notification method matches and delivery has not started. ### Method Signature ```csharp protected abstract Task InternalHandleEventAsync(EntityCreatedEventData eventData) ``` ### Parameters #### Path Parameters - **eventData** (EntityCreatedEventData) - Created Notification entity wrapped in event data ``` -------------------------------- ### CreateSmsNotificationEto Constructor with Multiple User IDs Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/sms-provider.md Constructs a `CreateSmsNotificationEto` object using a collection of user IDs. ```csharp public CreateSmsNotificationEto( Guid? tenantId, IEnumerable userIds, string text, IDictionary properties, IJsonSerializer jsonSerializer) ``` -------------------------------- ### Create UserWelcomeNotificationEto with Factory Source: https://github.com/easyabp/notificationservice/blob/master/docs/README.md Defines a notification factory to create `CreateSmsNotificationEto` from custom data models. Implement `ITransientDependency` for automatic dependency injection. ```csharp public class UserWelcomeNotificationFactory : NotificationFactory, ITransientDependency { public override async Task CreateAsync( UserWelcomeNotificationDataModel model, IEnumerable userIds) { var text = $"Hello, {model.UserName}, here is a gift card code for you: {model.GiftCardCode}"; return new CreateSmsNotificationEto(CurrentTenant.Id, userIds, text, new Dictionary()); } } ``` -------------------------------- ### NotificationInfo Constructors Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/notification-domain-classes.md Demonstrates the constructors for the NotificationInfo class, used for creating and initializing notification objects. ```APIDOC ## NotificationInfo Constructors ### Constructor 1 ```csharp public NotificationInfo(Guid id, Guid? tenantId) ``` **Parameters** | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | id | Guid | Yes | — | Unique identifier | | tenantId | Guid? | No | null | Multi-tenancy identifier | **Usage Example** ```csharp var notificationInfo = new NotificationInfo( id: Guid.NewGuid(), tenantId: currentTenant.Id ); ``` ### Constructor 2 ```csharp public NotificationInfo( Guid id, Guid? tenantId, Dictionary dataDictionary) ``` Initializes with pre-populated data values. **Parameters** | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | id | Guid | Yes | — | Unique identifier | | tenantId | Guid? | No | null | Multi-tenancy identifier | | dataDictionary | Dictionary | Yes | — | Key-value pairs for custom notification data | ``` -------------------------------- ### Send Notifications Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/README.md Demonstrates two methods for sending notifications: background sending via event bus and quick sending for immediate delivery. ```csharp // Create factory var factory = serviceProvider.GetRequiredService(); var model = new WelcomeModel { UserName = "John" }; // Option 1: Background sending var eto = await factory.CreateAsync(model, userId); await distributedEventBus.PublishAsync(eto); // Option 2: Quick send (immediate) var results = await notificationIntegrationService.QuickSendAsync(eto); ``` -------------------------------- ### Send Email Notification Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/README.md Use CreateEmailNotificationEto to create an email notification and publish it via the distributed event bus for background sending, or use QuickSendAsync for immediate sending. ```csharp var eto = new CreateEmailNotificationEto( tenantId: Guid.NewGuid(), userIds: new[] { userId }, subject: "Order Confirmation", body: "

Your order #12345 has been confirmed.

"); // Send in background await distributedEventBus.PublishAsync(eto); // Or send immediately var results = await notificationIntegrationService.QuickSendAsync(eto); ``` -------------------------------- ### IExternalUserLookupServiceProvider Interface Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/repositories-and-infrastructure.md Defines a service for resolving user information (name, email, phone) by user ID. Includes the interface definition and usage examples. ```APIDOC ## IExternalUserLookupServiceProvider ### Description Service for resolving user information (name, email, phone) by user ID. ### Interface Definition ```csharp public interface IExternalUserLookupServiceProvider { Task FindByIdAsync(Guid id); } ``` ### IUserData Interface ```csharp public interface IUserData { Guid Id { get; } string UserName { get; } string Email { get; } string PhoneNumber { get; } string Name { get; } string Surname { get; } } ``` ### Usage in Notification Managers This example shows how to use `ExternalUserLookupServiceProvider.FindByIdAsync` to resolve user names from IDs when creating notifications. ```csharp protected async Task> CreateNotificationsAsync( NotificationInfo notificationInfo, CreateNotificationInfoModel model) { if (model.Users is not null) { // Use pre-resolved user info return model.Users.Select(user => new Notification( GuidGenerator.Create(), CurrentTenant.Id, user.Id, user.UserName, notificationInfo.Id, NotificationMethod)).ToList(); } var notifications = new List(); // Resolve user names from IDs foreach (var userId in model.UserIds) { var user = await ExternalUserLookupServiceProvider.FindByIdAsync(userId); var userName = user?.UserName ?? UnknownUserName; notifications.Add(new Notification( GuidGenerator.Create(), CurrentTenant.Id, userId, userName, notificationInfo.Id, NotificationMethod)); } return notifications; } ``` ``` ```APIDOC ## Custom Implementation of IExternalUserLookupServiceProvider ### Description Provides a template for creating a custom implementation of the `IExternalUserLookupServiceProvider` interface, demonstrating how to fetch user data from a custom repository. ### Code Example ```csharp public class CustomUserLookupProvider : IExternalUserLookupServiceProvider, ITransientDependency { private readonly IRepository _userRepository; public async Task FindByIdAsync(Guid id) { var user = await _userRepository.FindAsync(id); if (user == null) return null; return new UserData { Id = user.Id, UserName = user.UserName, Email = user.Email, PhoneNumber = user.PhoneNumber, Name = user.FirstName, Surname = user.LastName }; } } ``` ### Registration To use the custom provider, register it in your module: ```csharp context.Services.ReplaceTransient(); ``` ``` -------------------------------- ### Usage of TeamAnnouncementFactory Source: https://github.com/easyabp/notificationservice/blob/master/_autodocs/api-reference/private-messaging-provider.md Demonstrates how to use the `TeamAnnouncementFactory` to create and send a private message notification. It shows obtaining the factory from the service provider and using the `notificationIntegrationService`. ```csharp var factory = serviceProvider.GetRequiredService(); var model = new TeamAnnouncementModel { Title = "Q4 Goals", Content = "New goals for Q4 have been announced in the company portal." }; // Send private message immediately var eto = await factory.CreateAsync(model, teamMemberIds); var results = await notificationIntegrationService.QuickSendAsync(eto); foreach (var notification in results.Items) { if (notification.Success.HasValue) { Console.WriteLine($"Message sent to user {notification.UserId}: {notification.Success}"); } } ``` -------------------------------- ### Configure prefix-only timeago format Source: https://github.com/easyabp/notificationservice/blob/master/host/EasyAbp.NotificationService.Web.Unified/wwwroot/libs/timeago/locales/README.md Use prefixAgo and prefixFromNow settings for languages like Greek, leaving suffix settings empty. ```text [prefixAgo] 2 minutes [prefixFromNow] 2 minutes ```