Hi,
We have 2 different level extension system.
ExtraProperties property of the entity and data is carried over ExtraProperties in the DTO.If you used only one of them, can you try extending your object with 2 options at the same time?
Entity extensions should directly affect to angular UI and can be shown in the pre-built module pages without changing anything
Hi,
You can easily pick entities from modules while building one-to-many relation like this:
But while building many-to-many relations, there is no option for it. You'll go to Advanced tab and fill fields manually.
Let's say you want to build a relation for IdentityUser located at here: https://github.com/abpframework/abp/blob/dev/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs
Fill Entity namespace and Entity name fields manually like below:

If entities from modules cannot be loaded to that dropdown you can always use Advanced tab and fill information manually.
There might be some reasons that prevents reading entities from modules such as compilation errors or project doesn't have bin & obj folders. Make sure you build your project once, and make sure your project doesn't have any compilation error.
Hi,
We're investigating the case right now, Our ABP Suite team will respond as soon as possible to this issue
Can you try to access current user by API that is provided by ABP: https://abp.io/docs/latest/framework/ui/angular/current-user
currentUser object has id field on it
const currentUser = this.config.getOne("currentUser");
console.log(currentUser.id);
Hi,
Do you use LeptonX theme?
And how you were using this scrollbar API in your application? That might be an internal API that you used in javascript
Hi,
I investigated how system works and found the following points.
The following method is called from everywhere whenever event name required: https://github.com/abpframework/abp/blob/97e10cc7b2b849b0aebf2aa00881616d036b0af1/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/EventNameAttribute.cs#L22 Since this is a static method, it cannot be overriden in your project.
Another option seems like overriding RabbitMqDistributedEventBus in your project. Here is the original source code of that class:
https://github.com/abpframework/abp/blob/rel-9.1/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs
using Microsoft.Extensions.Options;
using RabbitMQ.Client;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.EventBus.Local;
using Volo.Abp.EventBus.RabbitMq;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.RabbitMQ;
using Volo.Abp.Timing;
using Volo.Abp.Tracing;
using Volo.Abp.Uow;
namespace MyCompanyName.MyApplicationName;
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IDistributedEventBus), typeof(RabbitMqDistributedEventBus), typeof(IRabbitMqDistributedEventBus))]
public class MyRabbitMqDistributedEventBus : RabbitMqDistributedEventBus
{
public MyRabbitMqDistributedEventBus(
IOptions<AbpRabbitMqEventBusOptions> options,
IConnectionPool connectionPool,
IRabbitMqSerializer serializer,
IServiceScopeFactory serviceScopeFactory,
IOptions<AbpDistributedEventBusOptions> distributedEventBusOptions,
IRabbitMqMessageConsumerFactory messageConsumerFactory,
ICurrentTenant currentTenant,
IUnitOfWorkManager unitOfWorkManager,
IGuidGenerator guidGenerator,
IClock clock,
IEventHandlerInvoker eventHandlerInvoker,
ILocalEventBus localEventBus,
ICorrelationIdProvider correlationIdProvider) : base(options, connectionPool, serializer, serviceScopeFactory, distributedEventBusOptions, messageConsumerFactory, currentTenant, unitOfWorkManager, guidGenerator, clock, eventHandlerInvoker, localEventBus, correlationIdProvider)
{
}
public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory)
{
var handlerFactories = GetOrCreateHandlerFactories(eventType);
if (factory.IsInFactories(handlerFactories))
{
return NullDisposable.Instance;
}
handlerFactories.Add(factory);
if (handlerFactories.Count == 1)
{
// Here we are registering the consumer for the first time.
Consumer.BindAsync( "SomePrefix_" + EventNameAttribute.GetNameOrDefault(eventType));
}
return new EventHandlerFactoryUnregistrar(this, eventType, factory);
}
protected override Task PublishAsync(IModel channel, string eventName, byte[] body, Dictionary<string, object>? headersArguments = null, Guid? eventId = null, string? correlationId = null)
{
eventName += "SomePrefix_" + eventName;
return base.PublishAsync(channel, eventName, body, headersArguments, eventId, correlationId);
}
private List<IEventHandlerFactory> GetOrCreateHandlerFactories(Type eventType)
{
return HandlerFactories.GetOrAdd(
eventType,
type =>
{
var eventName = EventNameAttribute.GetNameOrDefault(type);
EventTypes.GetOrAdd(eventName, eventType);
return new List<IEventHandlerFactory>();
}
);
}
}
In that case, you'll override this service both consumer & publisher projects to make consistency.
Can you check your application logs? There should be log that indicates which action fails for authentication. Then we can take action accordingly
Maintaining yet another solution does not seem like a great idea to me. Nor is it great to add coupling from numerous solutions by adding a Domain.Shared reference to the management solution for the sake of localizing a page.
But as I understand, there is no other option. Well, actually one more - a trade-off option - could be to make API request to abp/application-localization of each solution (supposing that all of them will be running in the production system) and to create a client-side dictionary (dictionaries), then - to extract the display name by the given localization key...
Instead of maintaining another project, you can use a shared access data source, like a shared CDN folder for json localization files or a shared redis cache that all applications can access directly etc. It depends how much flkexibility you need
Create a file named account.js in the same folder alongside Account/Default.cshtml file.
Set the content:
$(function () {
var $form = $('#tenant-switch-form');
if ($form.length > 0) {
$form.on('submit', function (e) {
e.preventDefault();
var $this = $(this);
var formData = $this.serialize();
var action = $this.attr('action') || window.location.pathname;
var method = $this.attr('method') || 'post';
$.ajax({
url: action,
type: method.toUpperCase(),
data: formData,
success: function (data, status, xhr) {
// On success, reload the page
window.location.reload();
},
error: function (xhr, status, error) {
alert('Tenant switch failed: ' + (xhr.responseText || error));
}
});
});
}
});
Account/Default.cshtml <script src="~/Themes/LeptonX/Layouts/Account/account.js"></script>
id="tenant-switch-form" to the tenant switch form. It should be looking like that: <form id="tenant-switch-form" method="post" asp-page="/Abp/MultiTenancy/TenantSwitchModal">
<select name="Input.Name"
class="auto-complete-select"
<!--
...
-->