Thanks Liming, I think I see where my confusion was.
I was thinking of generate-proxy as only targeting the default app module, but I've been reminded that proxies can be generated for a specific module key (if listed in /api/abp/api-definition).
So if I understand correctly, the distributed modulecan remain structured normally, with its API surface exposed under its own module key. Then, on the React side, the consuming host would generate proxies for both its own app module and for my distributed module, unless we create our own convention for shipping/generated API clients inside our React npm package.
That answers my question. Thanks for clarifying.
Thank you, Liming!
Just to confirm I understood the proxy guidance correctly: historically, distributable modules were responsible for their own app services and proxy layer. The app services for the module would exist within their own module (per /api/abp/api-definition), and the Angular frontend package would ship with the appropriate proxies to communicate with that app service layer. In your React example, you mentioned that the host application, not the distributed module, would be responsible for generating the proxies. Does this mean that, for the modern React stack, the distributed module's app service layer should be exposed through the main application module? This could complicate things if we need to support both an Angular UI (where the app services and proxies are owned by the module) and a React UI (where the app services may need to be merged into the main app module).
Secondly, it is important for me to understand ABP’s direction before I commit my company to an approach. Can you confirm whether ABP’s new naming scheme — Angular = classic, React = modern — signals that ABP is committing to a shift away from Angular and toward a new React-based frontend? Or, with the pending Hybrid UI infrastructure, is ABP’s long-term direction more that UI modules should eventually be framework-neutral? If the latter, I would suggest reconsidering the classic/modern naming, since it implies an intended migration path from Angular to React.
The practical reason I’m asking is that we need to decide how to build reusable modules today. It would be useful to know whether the recommended path forward is Angular or React, or whether this is something we should wait on until the Hybrid UI spec is more clearly defined.
I'm awaiting a response from a human and hoping the AI response is based on limited documentation rather than the intended direction. The response as presented is disappointing.
Although my read may be incorrect, given the relabeling of React as "modern" and Angular as "classic", it seems reasonable to assume that React is intended to become the primary UI stack going forward. If that's the case, I would expect the React ecosystem to support a proper module integration model, including the ability to build and deliver self-contained modules with both backend and frontend pieces. ABP itself already does this with modules like Text Templating, CMS Kit, Identity, etc., so it would be surprising if custom modules could not follow a similar pattern. Expecting module consumers to build their own frontend for each reusable module feels like a significant limitation and weakens the value of ABP's modular architecture.
Additionally, the public React app / Admin Console split is a great direction and solves a real pain point. However, based on the current documentation and AI response, it seems like custom module management pages may need to be added to the public React app rather than contributed into the Admin Console. If that is accurate, I think that is a mistake. It is common to need both a public site and an admin site, and module-provided UI should be targetable to either the public or admin console as needed.
So the main question is: is the modern React UI intended to support true frontend modularity for custom modules? If yes, it would be helpful to understand the planned extension points. If no, that has significant implications for anyone building reusable ABP modules on the modern React stack.
I no longer have the logs, but I can tell you they did not. It went through a dotnet restore process, then exited with no further output. Not sure if relevant, but this is on ABP v9.x
We have file logging disabled - we prefer db logging. The db logs don't include any mention of needing to login. We also tried launching with dotnet run and saw no messages about why the application was aborting.
"Serilog": {
"Using": [ "Serilog.Sinks.MSSqlServer", "Serilog.Sinks.Console" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.EntityFrameworkCore": "Warning",
"System": "Warning"
}
},
"Enrich": [ "FromLogContext", "WithMachineName" ],
"Properties": {
"Application": "Elite Tenants Platform"
},
"WriteTo": [
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "Default",
"sinkOptionsSection": {
"tableName": "Logs",
"autoCreateSqlTable": true
},
"restrictedToMinimumLevel": "Warning",
"columnOptionsSection": {
"additionalColumns": [
{
"ColumnName": "MachineName",
"DataType": "varchar",
"DataLength": 50
},
{
"ColumnName": "UserId",
"DataType": "uniqueidentifier",
"NonClusteredIndex": true
}
]
}
}
}
]
},
This should not be logged as "Information", this should be thrown as a critical error if it's going to abort execution.
Gotcha! Thanks for your help on this!
Thank you. The example you provided got me what I needed. I removed the tenancy check (since we're not using multi-tenancy in our application) and ended up with this revised version (below).
A couple things I need:
protected override async Task TrySetEmailAsync()
{
if (IsExternalLogin)
{
var externalLoginInfo = await SignInManager.GetExternalLoginInfoAsync();
if (externalLoginInfo == null)
{
return;
}
if (!externalLoginInfo.Principal.Identities.Any())
{
return;
}
var identity = externalLoginInfo.Principal.Identities.First();
var emailClaim = identity.FindFirst(AbpClaimTypes.Email) ?? identity.FindFirst(ClaimTypes.Email);
var givenNameClaim = identity.FindFirst(AbpClaimTypes.Name) ?? identity.FindFirst(ClaimTypes.GivenName);
var surnameClaim = identity.FindFirst(AbpClaimTypes.SurName) ?? identity.FindFirst(ClaimTypes.Surname);
if (emailClaim == null)
{
return;
}
var userName = await UserManager.GetUserNameFromEmailAsync(emailClaim.Value);
Input = new PostInput
{
EmailAddress = emailClaim.Value,
FirstName = givenNameClaim?.Value ?? "",
LastName = surnameClaim?.Value ?? "",
};
}
}
For authentication we should define a new OpenID application within ABP and configure Elsa Studio to authenticate via OIDC? Or perhaps there's a simpler way to accomplish this as Elsa Server is hosted within the ABP project, so should have direct access to the Identity provider.