Version 13.4.0, Angular 18, .NET 8
Hi Support,
We are experiencing an issue when trying to use entity notifications. Basically when an entity notification is published, we get the below JavaScript error at the angular side with result the notifications bar and also the notifications page not fetching any data at all.
After some investigation I see that the record that is added to AbpTenantNotifications is responsible to produce this error and if I make the Entity fields (EntityId, EntityTypeAssemblyQualifiedName, EntityTypeName) NULL then all works and the new notification as well as all previous are shown properly.
ERROR SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data handleErrorResponse zero-template-http-interceptor.ts:20 RxJS 3 onload abp-ng2-module.mjs:454 Angular 5 core.mjs:7404:23
Please advise!
Thanks, Loizos
5 Answer(s)
-
0
Hi support,
Is there any update on this?
Thanks Loizos
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hi @Loizos
Sorry for the late response. In order to reproduce this issue in your case, could you please send your project to [email protected]? This way, we can provide you with a faster and more specific response.
Thank you
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hi @oguzhanagir
I am afraid I cannot send entire project. Is there any other option?
Did you attempt to replicate it at your side at all? We haven't changed anything from core/out of the box code. We just try to use entity notifications. Subscribe works fine as we want it. When publish though to any notifier it produces above problem.
Loizos
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hi @Loizos
Thank you for the follow up. We have analyzed the issue and can confirm the problem is related to how entity notification data is serialized. You can resolve this without sending us the entire project by implementing the following changes. We also created an issue for this, you can follow the developments here.
The root cause is the
EntityTypeproperty (which is aSystem.Typeobject) within theTenantNotificationclass. The .NET JSON serializer converts this property into a complex object that the Angular client cannot parse, leading to theJSON.parseerror. The[Obsolete]attribute on this property in ABP's source code already warns that this is a known bad practice.The solution is to use Data Transfer Objects (DTOs) to send a "clean" version of the notification data to the client, without the problematic
EntityTypeproperty.Here is a step by step guide to fix this:
Define Your Safe Notification DTOs
First, ensure you have your own set of DTOs for notifications. Based on your code, you have already done this correctly by creating classes in the
MyCompanyName.AbpZeroTemplate.Notifications.Dtonamespace and removing theEntityTypeproperty. This is the correct approach.For clarity, these are the DTOs you should have:
// In a file like /Notifications/Dto/UserNotificationDto.cs namespace MyCompanyName.AbpZeroTemplate.Notifications.Dto { [Serializable] public class UserNotification : EntityDto<Guid>, IUserIdentifier { public int? TenantId { get; set; } public long UserId { get; set; } public UserNotificationState State { get; set; } public TenantNotification Notification { get; set; } // Other properties... } [Serializable] public class TenantNotification : EntityDto<Guid>, IHasCreationTime { public string NotificationName { get; set; } public NotificationData Data { get; set; } public string EntityTypeName { get; set; } // This string version is safe public object EntityId { get; set; } public NotificationSeverity Severity { get; set; } public DateTime CreationTime { get; set; } // The problematic 'public Type EntityType { get; set; }' is correctly removed. } }Update the
NotificationAppServiceNext, modify the
GetUserNotificationsmethod in yourNotificationAppService.csto map the original notification objects to your new safe DTOs before returning them.// In NotificationAppService.cs public async Task<GetNotificationsOutput> GetUserNotifications(GetNotificationsInput input) { var totalCount = await _userNotificationManager.GetUserNotificationCountAsync( AbpSession.ToUserIdentifier(), input.State, input.StartDate, input.EndDate ); var unreadCount = await _userNotificationManager.GetUserNotificationCountAsync( AbpSession.ToUserIdentifier(), UserNotificationState.Unread, input.StartDate, input.EndDate ); var notifications = await _userNotificationManager.GetUserNotificationsAsync( AbpSession.ToUserIdentifier(), input.State, input.SkipCount, input.MaxResultCount, input.StartDate, input.EndDate ); // Map the framework objects to your safe DTOs var notificationDtos = ObjectMapper.Map<List<Dto.UserNotification>>(notifications); // Return the GetNotificationsOutput with your DTO list return new GetNotificationsOutput(totalCount, unreadCount, notificationDtos); }Configure AutoMapper
The
ObjectMapper.Mapcall requires mapping rules. You must tell AutoMapper how to convert the framework's notification types to your DTOs. Add the following configuration toCustomDtoMapper.csin your.Applicationproject.// In CustomDtoMapper.cs using MyCompanyName.AbpZeroTemplate.Notifications.Dto; //... internal static class CustomDtoMapper { public static void CreateMappings(IMapperConfigurationExpression configuration) { // ... other existing mappings // Add these two lines to define the mapping rules configuration.CreateMap<Abp.Notifications.UserNotification, UserNotification>(); configuration.CreateMap<Abp.Notifications.TenantNotification, TenantNotification>(); } }Ensure
GetNotificationsOutputUses Your DTOFinally, confirm that your
GetNotificationsOutputclass uses your customUserNotificationDTO. Your provided code is already correct.// In /Notifications/Dto/GetNotificationsOutput.cs // The generic type PagedResultDto<UserNotification> correctly refers to your DTO // in the MyCompanyName.AbpZeroTemplate.Notifications.Dto namespace. public class GetNotificationsOutput : PagedResultDto<UserNotification> { public int UnreadCount { get; set; } public GetNotificationsOutput(int totalCount, int unreadCount, List<UserNotification> notifications) : base(totalCount, notifications) { UnreadCount = unreadCount; } }By following these steps, you are intercepting the problematic data from the framework and transforming it into a clean, safe format before it is sent to the Angular client. This will resolve the
JSON.parseerror.Please let us know if this solves the issue.
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hi @oguzhanagir,
Thanks for your answer. So basically we've solved it by adding below line of code in NotificationAppService/GetUserNotifications, as a temporary solution. Once you fix it in your next release we will remove it.
notifications.ForEach(notification => notification.Notification.EntityType = null);
Thanks, Loizos
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image)