Browse Source

Merge remote-tracking branch 'origin/dev' into pr25847-resolve

# Conflicts:
#	docs/en/framework/infrastructure/audit-logging.md
pull/25847/head
maliming 2 months ago
parent
commit
5bd1533ebe
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 4
      common.props
  2. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/gifs/designer-hybrid-flow.gif
  3. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/gifs/runtime-workflow.gif
  4. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/code-backlog-summary.png
  5. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/custom-endpoint-summary.png
  6. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-code-layer.png
  7. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-devjson-endpoint.png
  8. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-devjson-entity.png
  9. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-devjson-form.png
  10. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-devjson-page.png
  11. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-enum-status-modal.png
  12. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-enum-status-saved.png
  13. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-form-create-modal.png
  14. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-page-create-before-save.png
  15. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-review-template-properties.png
  16. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-runtime-entity.png
  17. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-vendor-application-properties.png
  18. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-vendor-escalation-save-modal.png
  19. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/runtime-form-documents.png
  20. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/runtime-grid-filtered.png
  21. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/runtime-review-rejected.png
  22. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/runtime-vendor-escalations.png
  23. BIN
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/cover.png
  24. 394
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/post.md
  25. 1
      docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/summary.md
  26. BIN
      docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/gifs/eventflow-calendar-kanban-flow.gif
  27. BIN
      docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/gifs/eventflow-custom-endpoint-flow.gif
  28. BIN
      docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/gifs/eventflow-grid-form-flow.gif
  29. BIN
      docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/gifs/eventflow-hero-loop.gif
  30. BIN
      docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/gifs/eventflow-page-builder.gif
  31. BIN
      docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/screenshots/abp-studio-lowcode-system.png
  32. BIN
      docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/screenshots/admin-console-lowcode.png
  33. BIN
      docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/screenshots/overview-dashboard.png
  34. BIN
      docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/screenshots/sponsor-activation-form.png
  35. BIN
      docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/cover.png
  36. 225
      docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/post.md
  37. 1
      docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/summary.md
  38. 221
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/deep-research-report (2).md
  39. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/0ecaa3f6-5bb3-48f5-b5f5-075d1a3655c3.png
  40. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/6ba4a151-50f2-46cd-a8b6-81d1002914d2.png
  41. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/73587b76-e4d5-4ee7-9cd1-ce1ec868d763.png
  42. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/adc46f52-de83-4ab5-ad6a-06c84e7f46d8.png
  43. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/bbe4472b-f748-4360-8293-8edacecf45bc.png
  44. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/bc5ba15a-0e47-42ac-b08f-c4e05bb9bc16.png
  45. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/bf456714-fd6a-43ca-8d60-2b83b45ba92c.png
  46. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/cb89efeb-0d66-40e6-97c6-43b652ea7445.png
  47. 221
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/deep-research-report (2).md
  48. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/wearedevelopers-world-congress-2026-berlin-ticket-D4CZ-1.pdf
  49. 96
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/empathy-in-the-workplace.md
  50. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/closing.png
  51. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/empathy-loop.png
  52. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/hero.png
  53. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/practice.png
  54. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/quote.png
  55. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/roles.png
  56. BIN
      docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/why-empathy.png
  57. 64
      docs/en/Community-Articles/2026-07-17-WAD-RECAP/post.md
  58. 2
      docs/en/framework/api-development/auto-controllers.md
  59. 4
      docs/en/framework/architecture/domain-driven-design/unit-of-work.md
  60. 2
      docs/en/framework/infrastructure/audit-logging.md
  61. 4
      docs/en/suite/create-solution.md
  62. 2
      docs/en/suite/creating-many-to-many-relationship.md
  63. 2
      docs/en/suite/creating-master-detail-relationship.md
  64. 2
      docs/en/suite/customizing-the-generated-code.md
  65. 7
      docs/en/suite/editing-templates.md
  66. 2
      docs/en/suite/generating-crud-page.md
  67. 2
      docs/en/suite/index.md
  68. 5
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs
  69. 5
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs
  70. 6
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs
  71. 8
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider.cs
  72. 1
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs
  73. 1
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs
  74. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs
  75. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFrameworkExtensions.cs
  76. 9
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs
  77. 62
      framework/src/Volo.Abp.Http/Volo/Abp/Http/HttpMethodHelper.cs
  78. 14
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs
  79. 11
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkMiddleware_Tests.cs
  80. 11
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Tests.cs
  81. 10
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestController.cs
  82. 8
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml.cs
  83. 32
      framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider_Tests.cs
  84. 64
      framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/AuditingInterceptor_HttpMethod_Tests.cs
  85. 2
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/IRegularTestController.cs
  86. 7
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs
  87. 8
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs
  88. 105
      framework/test/Volo.Abp.Http.Tests/Volo/Abp/Http/HttpMethodHelper_Tests.cs
  89. 1
      modules/docs/src/Volo.Docs.Admin.HttpApi.Client/Volo.Docs.Admin.HttpApi.Client.csproj
  90. 1
      modules/docs/src/Volo.Docs.Admin.HttpApi.Client/Volo/Docs/Admin/DocsAdminHttpApiClientModule.cs
  91. 1
      modules/docs/src/Volo.Docs.HttpApi.Client/Volo.Docs.HttpApi.Client.csproj
  92. 1
      modules/docs/src/Volo.Docs.HttpApi.Client/Volo/Docs/DocsHttpApiClientModule.cs
  93. 6
      npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.html
  94. 2
      npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html
  95. 12
      npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts

4
common.props

@ -1,8 +1,8 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>10.6.0-rc.2</Version>
<LeptonXVersion>5.6.0-rc.2</LeptonXVersion>
<Version>10.7.0-preview</Version>
<LeptonXVersion>5.7.0-preview</LeptonXVersion>
<NoWarn>$(NoWarn);CS1591;CS0436</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io/</PackageProjectUrl>

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/gifs/designer-hybrid-flow.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/gifs/runtime-workflow.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/code-backlog-summary.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/custom-endpoint-summary.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-code-layer.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-devjson-endpoint.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-devjson-entity.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-devjson-form.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-devjson-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-enum-status-modal.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-enum-status-saved.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-form-create-modal.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-page-create-before-save.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-review-template-properties.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-runtime-entity.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-vendor-application-properties.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/designer-vendor-escalation-save-modal.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/runtime-form-documents.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/runtime-grid-filtered.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/runtime-review-rejected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/assets/screenshots/runtime-vendor-escalations.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/cover.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

394
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/post.md

@ -0,0 +1,394 @@
# Building a Vendor Onboarding Workflow with ABP Low-Code
Vendor onboarding usually starts with a few familiar steps.
A company sends its details, someone checks the documents, another person reviews the score, and the team either approves the vendor or asks for more information. After a while, the process turns into a mix of spreadsheets, uploaded files, status notes, and "who is waiting on this one?" messages.
In this article, we'll build that workflow with the [Low-Code System](https://abp.io/docs/latest/low-code/index). We'll model the data in the [Low-Code Designer](https://abp.io/docs/latest/low-code/designer), let the [React runtime](https://abp.io/docs/latest/low-code/react-runtime) render the page, and then add one [custom endpoint](https://abp.io/docs/latest/low-code/custom-endpoints) for a summary that does not belong to normal CRUD.
The example is an internal operations page where a team receives vendor applications, reviews compliance documents, tracks deadlines, and follows rejected or priority vendors from one place.
That is a good place to try ABP Low-Code, because the first version of the workflow is mostly data, screens, validation rules, and a few process-specific actions. You do not need to hand-write a React page only to list vendor applications, upload a compliance document, or show a rejection reason when the status is rejected.
We will start from an already running ABP React + EF Core application with Low-Code enabled, so the article can stay focused on the Admin Console, the Designer, and the runtime flow.
## What We Are Building
The workflow has one main record: `VendorApplication`.
A reviewer should be able to:
- Create a vendor application with company and contact details.
- Track whether the vendor is `Submitted`, `InReview`, `Approved`, or `Rejected`.
- Set the requested date and approval deadline.
- Mark priority vendors.
- Assign a category such as `Software`, `Services`, or `Hardware`.
- Upload a logo and a compliance document.
- Fill in a rejection reason only when the application is rejected.
- Filter the generated grid by status, requested date, priority, and category.
- Call a summary endpoint that returns counts for dashboard-like use.
We'll also touch two extra pieces around that main record. `VendorReviewTemplate` comes from C# so you can see how code-defined metadata appears in the Designer. Later, a `VendorEscalation` model is added while the Designer is switched to `Runtime JSON`. You could build the whole workflow with one entry point, but using these three entry points makes the hybrid model visible without turning the article into three separate implementations.
## A Quick Note on How Low-Code Fits Together
The Low-Code Designer is where you describe the model and the UI metadata. In this article we use four areas:
- `Data` for enums and entities.
- `Pages` for the generated grid route.
- `Forms` for the create/edit form layout.
- `Actions` for the custom HTTP endpoint.
The Designer stores metadata. The React runtime reads that metadata and renders the page at runtime. That is the important mental model: when we add a field to the entity, the field can become a grid column, a filter, a validation rule, or a form input depending on how we configure the metadata around it.
There is also one database detail to keep in mind. Metadata that comes from C# code or from `Dev JSON` is source-controlled application metadata. When it introduces or changes a persisted entity, run the normal EF Core migration and database update flow before using the generated runtime page. In the validated demo for this article I used SQLite, so the migration updated the local SQLite database. `Runtime JSON` is different: it is authored at runtime, so I do not run a C# migration in that section.
## Add a Code-Defined Review Template
Let's start with one model that does not come from the Designer.
In this workflow, vendor reviewers can use review templates. The template itself is not the center of the workflow, so I kept it focused on the review rules:
```csharp
[DynamicEnum]
public enum VendorReviewTemplateType
{
Standard = 0,
Security = 1,
Finance = 2
}
[DynamicEntity(DefaultDisplayPropertyName = nameof(Name))]
[DynamicEntityUI(DisplayName = "Vendor Review Templates")]
public class VendorReviewTemplate : DynamicEntityBase
{
[Required]
[StringLength(128)]
[DynamicPropertyUnique]
public string Name { get; set; }
public VendorReviewTemplateType TemplateType { get; set; }
public int MinimumComplianceScore { get; set; }
public bool RequiresDocumentReview { get; set; }
public string? Notes { get; set; }
}
```
Then include the entity in your EF Core DbContext. This is the part that makes the migration create a real backing table for the code-defined model:
```csharp
public DbSet<VendorReviewTemplate> VendorReviewTemplates { get; set; }
builder.Entity<VendorReviewTemplate>(b =>
{
b.ToTable(
VendorOnboardingLowCodeConsts.DbTablePrefix + "VendorReviewTemplates",
VendorOnboardingLowCodeConsts.DbSchema
);
b.ConfigureByConvention();
b.Property(x => x.Name).IsRequired().HasMaxLength(128);
b.Property(x => x.Notes).HasMaxLength(512);
b.HasIndex(x => x.Name).IsUnique();
});
```
Because this model is defined in C#, treat it like the rest of your application schema changes: add the entity, add the DbSet/mapping, create/apply the EF Core migration, and then start the application.
After the app starts, open **Admin Console > Low-Code Designer > Data**. The model is visible there, but it is read-only because it was defined in code.
![Code-defined VendorReviewTemplate shown as read-only in the Low-Code Designer](assets/screenshots/designer-code-layer.png)
Open the **Properties** tab and you can see the fields that came from the C# class. They are available to the Low-Code System, but the Designer marks them as code-owned.
![The Properties tab for the code-defined VendorReviewTemplate entity](assets/screenshots/designer-review-template-properties.png)
That is useful in real projects. Some metadata can be shipped with the application, while the rest of the workflow can still be designed through the Admin Console.
## Create the Vendor Enums
Now move to the part we actually build in the Designer.
The animation below shows the Designer path in one pass. The next sections slow it down and explain the enum, entity, page, and form steps.
![Creating the Designer metadata for the vendor onboarding workflow](assets/gifs/designer-hybrid-flow.gif)
Open `Data > Enums` and create the status enum:
```text
VendorApplicationStatus
Submitted
InReview
Approved
Rejected
```
Before saving, the enum modal should contain the name and the four values:
![The VendorApplicationStatus enum creation modal before saving](assets/screenshots/designer-enum-status-modal.png)
Then create the category enum:
```text
VendorCategory
Software
Services
Hardware
```
The order of the status values matters for the custom endpoint later, because the script checks the enum values by their numeric indexes. In this example `Submitted` is `0`, `Approved` is `2`, and `Rejected` is `3`.
After saving, the enum detail page shows the numeric values that the runtime and scripts will use:
![The saved VendorApplicationStatus enum values in the Designer](assets/screenshots/designer-enum-status-saved.png)
## Create the VendorApplication Entity
Go to `Data > Entities` and create `VendorApplication`.
This is the model that drives the rest of the article. Add these fields:
| Field | Type | Configuration |
| --- | --- | --- |
| `CompanyName` | `String` | Required and unique |
| `ContactEmail` | `String` | Required, email validation |
| `Status` | `Enum` | `VendorApplicationStatus` |
| `RequestedOn` | `Date` | Application date |
| `ApprovalDeadline` | `Date` | Review deadline |
| `IsPriority` | `Boolean` | Priority flag |
| `Category` | `Enum` | `VendorCategory` |
| `ComplianceScore` | `Int` | Review score |
| `Logo` | `Image` | Logo upload |
| `ComplianceDocument` | `File` | Document upload |
| `RejectionReason` | `String` | Optional |
![VendorApplication entity definition in the Designer](assets/screenshots/designer-devjson-entity.png)
The **Properties** tab is where the entity becomes more than a name. The table shows the field types, enum bindings, and source layer. Scroll down and the upload-related fields are visible with their `Image` and `File` types:
![The VendorApplication properties table in the Designer](assets/screenshots/designer-vendor-application-properties.png)
There is no React code yet, but we already have a lot of behavior described: required fields, uniqueness, email validation, enum fields, upload fields, and the data shape that the runtime will use.
The `Image` and `File` types are worth calling out. They are not plain strings with a path. In the generated form they become upload controls, which is exactly what we need for vendor logos and compliance documents.
Since `VendorApplication` is authored in the `Dev JSON` layer, it also belongs to the source-controlled model. After saving the entity metadata, create/apply the EF Core migration before you open the generated page in the runtime. This is the step that creates the backing table for the low-code entity in the database.
## Generate a Grid Page
The reviewers need a page where they can work with applications, so go to `Pages` and create a `dataGrid` page named `vendor-onboarding`.
Bind it to `VendorApplication`.
Before saving the page, the modal connects the route name, title, icon, and entity:
![The vendor-onboarding data grid page modal before saving](assets/screenshots/designer-page-create-before-save.png)
After the page is created, set `RequestedOn` as the default sort field, keep it descending, adjust the icon if you want, and assign `vendor-application-form` as the create/edit form:
![The vendor-onboarding data grid page bound to VendorApplication](assets/screenshots/designer-devjson-page.png)
For the review workflow, keep the configured columns focused on the fields reviewers use most:
- Company name
- Status
- Requested date
- Priority
- Category
Then configure the filters you want reviewers to use most often. In this workflow, the important filters are company, status, requested date, priority, and category. Depending on the runtime defaults, the generated grid may still expose additional fields such as contact email; the workflow is still driven by the focused page metadata above.
Once the page is saved, the React runtime can resolve the route from the page metadata. The grid is generated from the entity and page configuration rather than from a hand-written React component.
## Build the Create/Edit Form
A grid is not enough. We also need a form that feels like the workflow.
Go to `Forms` and create `vendor-application-form` for `VendorApplication`. Split the fields into three tabs:
![The vendor-application-form creation modal before saving](assets/screenshots/designer-form-create-modal.png)
- **Company**: `CompanyName`, `ContactEmail`, `Category`, `IsPriority`
- **Review**: `Status`, `RequestedOn`, `ApprovalDeadline`, `ComplianceScore`, `RejectionReason`
- **Documents**: `Logo`, `ComplianceDocument`
Now add the conditional behavior for `RejectionReason`. In this demo I used two complementary rules: one rule shows the field when `Status = Rejected`, and the other hides it for non-rejected statuses.
![The vendor-application-form with tabs and a conditional rule](assets/screenshots/designer-devjson-form.png)
This is one of the places where Low-Code becomes more than "generate a CRUD page". The runtime does more than render a static form; it evaluates the rule while the user edits the record.
## Apply the Migration Before Opening the Runtime
Before opening the generated page, apply the database migration for the `Dev JSON` changes. We used `Dev JSON` for `VendorApplication`, so the Designer wrote source-controlled descriptor files under `_Dynamic`. The entity shape is now part of the application model, and the database needs the matching backing table before the React runtime can save records.
That is why `Dev JSON` is a good fit during development: the metadata files and the EF Core migration can be reviewed, committed, and reproduced in another environment. If the same entity had been created in the `Runtime JSON` layer, you would not create a C# migration for that runtime edit; the metadata change would be stored in the database instead. In practice, use `Dev JSON` for development-time, source-controlled changes, and use `Runtime JSON` when you want production-time changes to be managed from the Admin Console and persisted in the database.
## Try It in the React Runtime
Open the generated `vendor-onboarding` page in the React runtime and create a vendor application.
On the `Documents` tab, the `Logo` and `ComplianceDocument` fields are rendered as upload fields:
![The generated Documents tab rendering image and file upload fields](assets/screenshots/runtime-form-documents.png)
Now edit a record and change the status to `Rejected`. The `RejectionReason` field becomes available on the `Review` tab:
![The Review tab showing the conditional RejectionReason field](assets/screenshots/runtime-review-rejected.png)
After saving a few records, use the generated filters to narrow the list to rejected vendors. Depending on the runtime configuration, the filter panel can expose more fields than the small set you configured for the workflow; here we only use the `Status = Rejected` filter:
![The generated grid filtered by Status = Rejected](assets/screenshots/runtime-grid-filtered.png)
The short animation below gives a quick pass through the same runtime states: upload fields, the conditional rejection reason, and the filtered grid.
![Generated upload fields, conditional review field, and grid filters in the React runtime](assets/gifs/runtime-workflow.gif)
At this point we have a working page, form, validation, uploads, and filters. The important part is that all of it came from the metadata we configured in the Designer.
## Add a Custom Summary Endpoint
Generated CRUD is enough for day-to-day record editing, but teams often need one operation that is specific to their process.
For vendor onboarding, a summary endpoint is a good example:
```text
GET /api/custom/vendor-onboarding/summary
```
In the Designer, open `Actions` and create a custom HTTP action with that route. The script can use the [Scripting API](https://abp.io/docs/latest/low-code/scripting-api) to query the same `VendorApplication` data that the generated grid uses.
![The custom HTTP action configured under Actions in the Designer](assets/screenshots/designer-devjson-endpoint.png)
Here is the script used in the demo:
```js
var entityName = 'Acme.VendorOnboardingLowCode.Procurement.VendorApplication';
var vendorQuery = await db.query(entityName);
var totalVendors = await db.count(entityName);
var submittedVendors = await vendorQuery.where(x => x.Status === 0).count();
var approvedVendors = await vendorQuery.where(x => x.Status === 2).count();
var today = query.today || new Date().toISOString().slice(0, 10);
var overdueReviews = await vendorQuery
.where(x => x.ApprovalDeadline != null && x.ApprovalDeadline < today && x.Status !== 2)
.count();
return ok({
totalVendors: totalVendors,
submittedVendors: submittedVendors,
approvedVendors: approvedVendors,
overdueReviews: overdueReviews,
evaluatedOn: today
});
```
Use the entity name shown in your Designer. In the screenshots, it is `Acme.VendorOnboardingLowCode.Procurement.VendorApplication`.
When the endpoint runs, it returns the current counts from the low-code records:
![The JSON response of the custom summary endpoint](assets/screenshots/custom-endpoint-summary.png)
That is the bridge I like here. The page and form stay metadata-driven, but the process-specific summary is a short script exposed as a custom endpoint.
## Add One Runtime Model
Now switch the Designer layer to `Runtime JSON` and add one more entity: `VendorEscalation`.
This model represents the items that need extra attention. It could have been created in the same place as `VendorApplication`; I am adding it here only to show that runtime-authored metadata participates in the same Low-Code System.
Unlike the code and `Dev JSON` examples above, this runtime-authored model is not part of the source-controlled migration flow in this walkthrough.
The create modal is the same Designer experience, but the selected layer is now `Runtime JSON`:
![The VendorEscalation entity creation modal in the Runtime JSON layer](assets/screenshots/designer-vendor-escalation-save-modal.png)
![The VendorEscalation entity authored in the Runtime JSON layer](assets/screenshots/designer-runtime-entity.png)
Create a data grid page for it and open it in the React runtime:
![The runtime-generated Vendor Escalations page](assets/screenshots/runtime-vendor-escalations.png)
From the user's point of view, it behaves like the first generated page. From the metadata point of view, we have now seen code-defined metadata, Designer-authored metadata, and runtime-authored metadata in the same application.
## Read the Same Data from ABP Code
The last bridge is application code.
Sometimes the generated page is not the only consumer. You may want a typed application service, a scheduled job, or another API to read the same low-code records. The code below shows the idea by returning a backlog summary:
```csharp
private readonly IRepository<DynamicEntity, Guid> _vendorApplicationRepository;
private readonly IAsyncQueryableExecuter _queryableExecuter;
public async Task<VendorBacklogDto> GetBacklogAsync()
{
var entityDescriptor = DynamicModelManager.Instance.Find(
"Acme.VendorOnboardingLowCode.Procurement.VendorApplication"
);
if (entityDescriptor == null)
{
throw new UserFriendlyException("VendorApplication model was not found.");
}
var query = await _vendorApplicationRepository
.SetEntityName(entityDescriptor.Name)
.GetQueryableAsync();
var today = DateOnly.FromDateTime(Clock.Now);
var priorityQuery = query.Where(vendor =>
vendor.Data["IsPriority"] != null &&
(bool?)vendor.Data["IsPriority"] == true);
var nextPriorityVendor = await _queryableExecuter.FirstOrDefaultAsync(
priorityQuery.OrderByDescending(vendor =>
(DateOnly?)vendor.Data["RequestedOn"]));
return new VendorBacklogDto
{
TotalVendors = checked((int)await _queryableExecuter.LongCountAsync(query)),
PriorityVendors = checked((int)await _queryableExecuter.LongCountAsync(priorityQuery)),
RejectedVendors = checked((int)await _queryableExecuter.LongCountAsync(
query.Where(vendor =>
vendor.Data["Status"] != null &&
(int?)vendor.Data["Status"] == 3))),
OverdueReviews = checked((int)await _queryableExecuter.LongCountAsync(
query.Where(vendor =>
vendor.Data["ApprovalDeadline"] != null &&
(DateOnly?)vendor.Data["ApprovalDeadline"] < today &&
vendor.Data["Status"] != null &&
(int?)vendor.Data["Status"] != 2))),
NextPriorityVendor = nextPriorityVendor?.GetData<string>("CompanyName")
};
}
```
![The typed backlog summary returned by the application service](assets/screenshots/code-backlog-summary.png)
The important detail is that the aggregate operations stay on `IQueryable`; the code does not load every vendor into memory just to count them. This is not a replacement for the generated page. It is the other direction: use the generated page for the admin experience, then read the same records from normal ABP code when another part of the application needs them.
## Going Further
The workflow we built is intentionally focused, but the same shape can grow in a few directions:
- Add permissions around the generated pages and custom endpoint.
- Add more form rules for review-specific fields.
- Add an approval notification after a vendor is accepted.
- Add a scheduled job that checks overdue applications.
- Build a dashboard widget on top of the summary endpoint.
The main pattern stays the same: model the data in the Low-Code Designer, let the React runtime render the operational page, and add code or scripting only for the parts that are specific to your business process.
## Conclusion
ABP Low-Code is useful when the first version of a business workflow is mostly metadata: entities, fields, filters, forms, validation, uploads, and a few custom actions.
In this vendor onboarding example, the `VendorApplication` model gave us a generated grid and form, the runtime handled upload fields and conditional UI, and a custom endpoint added the summary that CRUD would not provide by itself. We also saw that low-code metadata can come from the Designer, from runtime JSON, or from C# code when you need that bridge.
That is the part worth remembering: you can start with a working admin experience quickly, then extend the workflow where the generated behavior stops being enough.
### Further Reading
- [Low-Code System Overview](https://abp.io/docs/latest/low-code/index)
- [Low-Code Designer](https://abp.io/docs/latest/low-code/designer)
- [React Runtime](https://abp.io/docs/latest/low-code/react-runtime)
- [Custom Endpoints](https://abp.io/docs/latest/low-code/custom-endpoints)
- [Scripting API](https://abp.io/docs/latest/low-code/scripting-api)

1
docs/en/Community-Articles/2026-07-07-building-a-vendor-onboarding-workflow-with-abp-low-code/summary.md

@ -0,0 +1 @@
Build a vendor onboarding workflow with ABP Low-Code: model vendor applications in the Designer, let the React runtime render the grid and form, then add a custom endpoint and a typed ABP code bridge for process-level counts.

BIN
docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/gifs/eventflow-calendar-kanban-flow.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

BIN
docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/gifs/eventflow-custom-endpoint-flow.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 KiB

BIN
docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/gifs/eventflow-grid-form-flow.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

BIN
docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/gifs/eventflow-hero-loop.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

BIN
docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/gifs/eventflow-page-builder.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

BIN
docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/screenshots/abp-studio-lowcode-system.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/screenshots/admin-console-lowcode.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/screenshots/overview-dashboard.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/assets/screenshots/sponsor-activation-form.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/cover.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

225
docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/post.md

@ -0,0 +1,225 @@
# Introducing ABP Low-Code: Build Real ABP Apps in Minutes
**Create runtime-managed pages, generated React screens, code-first C# entities, and Script API extensions without leaving the ABP application model.**
![ABP Low-Code runtime loop — grids, forms, calendars, and pipelines inside one ABP app](assets/gifs/eventflow-hero-loop.gif)
> **Want to try the same path?** Start from ABP Studio, enable the Low-Code runtime and designer, define pages in the Admin Console, and see them resolve inside the running ABP app.
---
## ABP Low-Code at a glance
| Runtime authoring | Generated screens | ABP-native extensibility | One application model |
| :---: | :---: | :---: | :---: |
| Define and update pages in the Admin Console | Grid, Form, Calendar, Kanban, Gallery, Dashboard | Code-first entities, Script API actions, and C# query paths | Runtime metadata, generated UI, and application code stay together |
---
## Built into the ABP Platform
Low-code is most useful when speed does not create a separate stack to maintain later.
That is where many low-code products start to strain. They move quickly at the beginning, then force a second implementation track when the app needs permissions, auditability, custom logic, or tighter integration with existing application code.
ABP Low-Code takes a different path. It runs **inside the ABP Platform**, so runtime-managed pages are part of an application foundation that already includes identity, permissions, audit logging, APIs, and code-level extensibility.
---
## Edit at runtime. See it in the app.
In the Low-Code Designer, you update a runtime-managed page. A few seconds later, the same application surface is visible in the live app. No rebuild loop. No parallel front-end implementation. No "we will wire it later" gap between authoring and runtime.
ABP Low-Code shortens the cycle from model change to running screen while keeping the output grounded in the same ABP application.
![ABP Low-Code designer workspace for a runtime page](assets/screenshots/admin-console-lowcode.png)
> **What this shows:** authoring and runtime are connected. Pages are defined in the designer and resolved in the running application.
---
## CRUD is table stakes
If low-code only saves you from drawing a table and a form, it is not enough. Business applications need richer operational surfaces.
In the generated app, the `Events` screen ships with search, actions, filters, and form-driven editing. The form structure already understands tabs, relations, validation, and business-shaped input instead of leaving you with a blank shell to finish by hand.
![Generated event grid and generated event form](assets/gifs/eventflow-grid-form-flow.gif)
The point is not just generated CRUD. It is generated CRUD that already looks like the operational screens teams maintain in real applications.
---
## One model, multiple operational screens
Business users do not think in one view. Operators want a calendar for scheduling, a kanban board for workflow, a grid for bulk operations, a gallery when media matters, and a dashboard when they need the state of the business at a glance.
ABP Low-Code keeps those surfaces attached to the same underlying model. The same `Session` model can appear as a **calendar** for planning and a **kanban pipeline** for operational flow. The same generated app can also include a **speaker gallery** and an **overview dashboard** for metrics.
![The same runtime model shown as calendar and kanban views](assets/gifs/eventflow-calendar-kanban-flow.gif)
![Overview dashboard in the live runtime app](assets/screenshots/overview-dashboard.png)
This is where ABP Low-Code starts to feel less like a form generator and more like a runtime application layer: one model, many working screens, no second implementation track for each view type.
---
## When low-code needs code
The real differentiator is not that ABP Low-Code can go fast. It is that **speed does not require isolation from the application foundation**.
When generated CRUD is not enough, you extend the same app instead of throwing the low-code layer away.
ABP Low-Code exposes a server-side **Script API** inside the same application model. That scripting surface can back:
- **Custom endpoints** when the UI needs an API-shaped response.
- **Interceptors** when create or update commands need validation or mutation.
- **Event handlers** when logic should react to runtime events.
- **Background jobs** when work should continue asynchronously.
- **Background workers** when operational logic should run on a schedule.
In this article, the visible proof happens to be `GET /api/custom/eventflow/highlights`. The GIF shows an endpoint because it is the easiest proof surface to read. But the broader point is that endpoints are only one consumer of the same low-code scripting layer.
That hybrid model matters in both directions:
- **Code-first ABP entities can be surfaced in low-code flows and runtime pages.**
- **Low-code-managed data and screens stay reachable from Script API actions, application services, repository queries, and custom endpoints.**
- **Teams do not lose architectural control just because they gained a faster authoring layer.**
![Endpoint result and runtime dashboard reading the same numbers](assets/gifs/eventflow-custom-endpoint-flow.gif)
The actual capability is the shared ABP application model behind it: script when runtime logic is enough, C# when typed application services and repository queries are the better fit.
This is the difference between "low-code as a shortcut" and "low-code as part of your application platform."
---
## From code-first entity to generated page
The first direction is code-first to low-code. A **code-first** `SponsorActivation` entity checked into the ASP.NET Core project can still become a working runtime page without forking into a separate low-code-only model.
The code-first entity carries the same metadata that ABP Low-Code uses to generate the page:
```csharp
[DynamicEntity(DefaultDisplayPropertyName = nameof(CompanyName))]
[DynamicEntityUI("Sponsor Activations")]
[DynamicEntityAttachments("application/pdf", "image/*", MaxFileCount = 4)]
public class SponsorActivation : DynamicEntityBase
{
[Required]
[DynamicPropertyUI(DisplayName = "Sponsor")]
public string CompanyName { get; private set; }
[Required]
[EmailAddress]
[DynamicPropertyUI(DisplayName = "Contact Email")]
public string ContactEmail { get; private set; }
public SponsorActivationStatus Status { get; set; }
[DynamicForeignKey("EventFlow.Events.Event", "Title")]
public Guid? EventId { get; set; }
[DynamicForeignKey("Volo.Abp.Identity.IdentityUser", nameof(IdentityUser.UserName), ForeignAccess.View)]
public Guid? OwnerUserId { get; set; }
[DynamicPropertyType(EntityPropertyType.Money)]
public decimal ActivationBudget { get; set; }
[DynamicPropertyImageOptions("image/png", "image/jpeg")]
public string? BrandLogo { get; set; }
[DynamicPropertyFileOptions("application/pdf", ".pptx", ".docx")]
public string? ActivationBrief { get; set; }
}
```
That class lives as normal C# source, gets migrated like the rest of the application, and is seeded with real records so the runtime page does not open as an empty shell.
Inside the designer, selecting the `SponsorActivation` entity auto-generates the page identity, binds the grid to the entity, and lands on a real runtime route at `/dynamic/sponsor-activation`. The generated surface includes sponsor, email, event lookup, owner lookup, budget, image, and file fields directly from the C# model.
![ABP Low-Code selecting the SponsorActivation C# entity, generating the page, and opening the resulting runtime surface](assets/gifs/eventflow-page-builder.gif)
![Generated SponsorActivation form showing lookups, budget, image, and file fields coming directly from the C# entity](assets/screenshots/sponsor-activation-form.png)
That is the distinction that matters: code-first ABP entities can move through low-code without becoming throwaway artifacts, and low-code-generated surfaces remain part of the same application story.
---
## Low-code data stays reachable from C#
The bridge also works in the other direction. A normal ABP application service can query a low-code model through `IRepository<DynamicEntity, Guid>`, apply real filters, and combine that result with code-first aggregates.
The service behind the endpoint in the previous section looks like this:
```csharp
public async Task<EventFlowLowCodeProofDto> GetHybridSummaryAsync()
{
var liveSessionQuery = (await _dynamicEntityRepository
.SetEntityName("EventFlow.Events.Session")
.GetQueryableAsync())
.Where("int(it[\"Status\"]) == @0", 2);
var publicSessionQuery = liveSessionQuery
.Where("bool(it[\"IsPublic\"]) == @0", true);
var sponsorQuery = (await _sponsorActivationRepository.GetQueryableAsync())
.Where(activation =>
activation.Status == SponsorActivationStatus.Approved ||
activation.Status == SponsorActivationStatus.Live);
var liveSessionCount = await AsyncExecuter.CountAsync(liveSessionQuery);
var publicSessionCount = await AsyncExecuter.CountAsync(publicSessionQuery);
var activeSponsorActivationCount = await AsyncExecuter.CountAsync(sponsorQuery);
return new EventFlowLowCodeProofDto
{
LiveSessionCount = liveSessionCount,
PublicSessionCount = publicSessionCount,
ActiveSponsorActivationCount = activeSponsorActivationCount
};
}
```
Here, low-code-managed `Session` rows are filtered from C# with real `Where(...)` clauses, then combined with the typed `SponsorActivation` repository. The endpoint and dashboard are just one presentation surface for that shared ABP query path.
That is the ABP difference: low-code data stays reachable from code, and code-first entities stay reachable from low-code.
---
## Why ABP Low-Code matters
The value is not novelty. It is a faster way to build real business applications without separating speed from the application foundation.
- **Speed without replatforming.** Runtime-managed screens reduce delivery time without moving the team onto a separate application stack.
- **Governance without friction.** Permissions, identity, auditability, and ABP platform foundations stay part of the story from day one.
- **Extensibility without rewrite pressure.** When custom behavior shows up, the same application can be extended instead of replacing the low-code output.
That is the core ABP Low-Code promise: faster delivery, still inside the application model you can extend.
---
## Try it yourself
The public starting point for ABP Low-Code is **ABP Studio**.
![ABP Studio new solution wizard with the Low-Code runtime and designer option enabled](assets/screenshots/abp-studio-lowcode-system.png)
1. Open **ABP Studio** and create a new solution.
2. In the solution wizard, enable **Include Low-Code runtime and designer**.
3. Complete the wizard, then run the generated backend and React UI from the solution.
4. Sign in with the administrator account created for that solution.
5. Open **Admin Console** to define runtime-managed entities, forms, pages, permissions, endpoints, and script actions.
6. Switch to the application side to see those changes resolve live in the running app.
---
## Further reading
- [ABP Low-Code Designer Documentation](https://abp.io/docs/latest/low-code/designer)
- [ABP Low-Code Configuration & Fluent API](https://abp.io/docs/latest/low-code/fluent-api)
- [ABP Low-Code Scripting API](https://abp.io/docs/latest/low-code/scripting-api)
- [ABP Low-Code Script Actions](https://abp.io/docs/latest/low-code/script-actions)
- [ABP Low-Code Interceptors](https://abp.io/docs/latest/low-code/interceptors)
- [ABP Studio Documentation](https://abp.io/docs/latest/studio)
- [Get Started with ABP: Creating a Layered Web Application](https://abp.io/docs/latest/get-started/layered-web-application)

1
docs/en/Community-Articles/2026-07-07-introducing-abp-low-code/summary.md

@ -0,0 +1 @@
Discover how ABP Low-Code blends runtime page building with code-first entities, C# queries, and extensible application logic.

221
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/deep-research-report (2).md

@ -0,0 +1,221 @@
# Empathy in the Workplace: The hidden skill behind a successful product
## Executive Summary
For a mid-size software company, workplace empathy should not be treated as a soft cultural slogan. The strongest evidence supports treating it as a disciplined, human-centered practice for understanding users’ goals, constraints, emotions, mental models, and tradeoffs, then using that understanding to improve what teams build, sell, market, and support. In software work, the most operationally useful form is usually **cognitive empathy** or **perspective-taking**: the deliberate effort to understand how another person interprets a feature, message, workflow, or pricing decision. **Affective empathy** matters too, because it motivates care and ethical concern, but on its own it is less reliable as an evaluation method and can produce distress or biased judgment if it is not structured. citeturn34view0turn29view1turn29view2turn28view3turn7search0turn28view0
Human-centered design standards and guidance point in the same direction: good systems are built on an explicit understanding of users, tasks, and environments; users are involved throughout design and development; evaluation is iterative; and multidisciplinary teams participate in the work. That makes empathy a cross-functional operating principle, not just a design-team activity. Developers, designers, sales, marketing, support, and product leaders all have relevant pieces of the customer reality. citeturn34view0turn34view1
For day-to-day practice, the most effective pattern is a repeatable loop: gather direct customer evidence, synthesize it in empathy maps or journey maps, run structured role-reversal critiques on a feature or message, validate with usability inspection and user testing, then connect findings to a small balanced scorecard of UX metrics and business outcomes. Google’s HEART framework, Brooke’s SUS, task-completion measures, and DORA-style delivery metrics are complementary here: together they help teams answer whether a feature is useful, usable, valuable, and operationally healthy. citeturn20view0turn33view1turn24view0turn23view0turn21view0turn22view0
The practical implication is straightforward: a software company should institutionalize empathy as a **review discipline**. Before release, teams should ask, from the viewpoint of a real user or buyer, “Would I understand what this is for, find it, trust it, complete the task, and feel the value was worth the effort?” After release, teams should ask, “Did the evidence improve activation, task success, retention, support burden, or conversion?” That combination of role-reversal and measurement is the most defensible way to make empathy evidence-based rather than rhetorical. citeturn20view0turn24view0turn23view0turn26view0turn25view0turn27view0
The table below condenses the report’s practical recommendations into an operating model for a mid-size software company. It synthesizes ISO human-centered-design principles, Google’s HEART and DORA guidance, NNGroup methods, Atlassian workshop practices, and company examples from IBM, Intuit, Microsoft, and GitHub. citeturn34view0turn20view0turn21view0turn26view0turn31view0turn31view4turn17view0turn31view2
| Operating area | Minimum recommendation | Why it matters |
|---|---|---|
| Product and UX | Run a structured empathy review on every material feature before release | Converts assumptions into observable critique, especially for learnability and value |
| Engineering | Add cognitive walkthroughs for new workflows and dogfooding with caution | Helps expose first-time-user friction, while recognizing employees are not the same as customers |
| Sales and marketing | Review landing pages, pricing pages, demos, emails, and onboarding copy from the buyer’s perspective | Brings empathy into acquisition and expectation-setting, not only UI |
| Measurement | Track one small balanced scorecard: task success, time or effort, perceived usability, adoption or activation, retention, and one business KPI | Prevents “feel-good empathy” without outcome accountability |
| Culture and process | Involve support, research, sales, and engineering in cross-functional reviews | Broadens perspective and reduces local optimization |
| Leadership | Protect psychological safety and blameless critique | Teams cannot surface customer pain honestly if they fear blame |
## What Empathy Means in a Software Company
Empathy is not one thing. Across psychology and design research, it is commonly treated as a multidimensional construct with at least two major components. **Affective empathy** refers to sharing or resonating with another person’s feeling state. **Cognitive empathy** refers to understanding another person’s viewpoint, intentions, needs, or mental state. Related work argues that empathy and perspective-taking should be conceptually separated, because affect sharing and cognitive perspective-taking can diverge and recruit different processes. citeturn29view1turn29view2turn28view3
That distinction matters in the workplace. If a software company wants teams to evaluate features, copy, onboarding, pricing pages, or service flows by “putting themselves in the user’s shoes,” the most reliable mechanism is usually **structured perspective-taking** rather than pure emotional resonance. Perspective-taking is the cognitive process of adopting another person’s viewpoint to understand their preferences, values, and needs. Work on organizations and creativity shows that perspective-taking helps employees generate ideas that are not only novel but also useful to other people inside and outside the organization. Other research shows it can improve negotiation and creative problem solving, which is especially relevant for sales, pricing, and product tradeoff discussions. citeturn28view0turn6search8turn7search0
Affective empathy still matters, but it should be used carefully. It is often the source of prosocial concern and ethical motivation, yet it can also become empathic distress or bias attention toward vivid pain rather than representative evidence. Recent reviews distinguish empathic distress from compassion and caution that empathy can have downsides when it is unstructured or emotionally overloading. A good software-company practice is therefore to pair an affective prompt such as “What frustration or anxiety is this causing?” with cognitive prompts such as “What is the user trying to achieve, what cues do they see, and what would they reasonably infer at this step?” citeturn28view3turn29view2turn29view1
In a software firm, empathy should also be understood as **human-centered evaluation across the full customer experience**, not just interface design. ISO and NIST guidance emphasize that human-centered design addresses the whole user experience, is driven by user-centered evaluation, and requires multidisciplinary perspectives. That means developers should empathize with first-time and edge-case users, designers with user cognition and accessibility needs, sales with the buyer’s decision journey and implementation anxieties, and marketing with the customer’s information needs and language during awareness, evaluation, trial, and adoption. citeturn34view0turn34view1
The strongest practical interpretation for a software company is this: **empathy is the disciplined replacement of internal assumptions with testable, role-reversed understanding**. It is not “Would I like this?” It is “Would this specific user or buyer, in this context, with this knowledge and these constraints, understand the value, succeed at the task, and consider the result worth the cost?” That framing aligns with human-centered design, cognitive walkthroughs, and modern UX benchmarking. citeturn34view0turn25view0turn24view0
## Methods for Role Reversal and Feature Critique
A software company does not need a single empathy method. It needs a **stack** of methods, each serving a different diagnostic purpose. Empathy maps are useful for capturing what users say, think, do, and feel, and for building shared understanding. Journey maps are better for exposing end-to-end friction, especially across acquisition, onboarding, support, and renewal moments. Cognitive walkthroughs are ideal when the question is learnability for a new user. Heuristic evaluations are strong for systematic usability inspection. Role play is useful when the room lacks real users or sufficient perspective diversity. Dogfooding is valuable for surfacing operational issues rapidly, but it is incomplete because employees often have too much institutional knowledge and use the product differently than real customers. citeturn25view1turn26view0turn25view0turn27view0turn25view3turn35view1turn26view0
```mermaid
flowchart LR
A[Direct customer evidence<br/>interviews, support logs, analytics, follow-me-homes] --> B[Shared artifact<br/>empathy map or journey map]
B --> C[Role-reversal review<br/>developers, designers, sales, marketing]
C --> D[Structured critique<br/>cognitive walkthrough and heuristic evaluation]
D --> E[Prototype or revise]
E --> F[Validate with users and analytics]
F --> G[Decision<br/>ship, iterate, or stop]
G --> A
```
The workflow above reflects the common structure across ISO human-centered design, Intuit’s deep-customer-empathy methods, NNGroup workshop guidance, and Google’s Goals-Signals-Metrics logic: start from real evidence, externalize it, inspect from the other person’s perspective, then validate with measurement. citeturn34view0turn32view1turn32view0turn25view3turn20view0
The comparison below is a practical selection guide for software teams.
| Method | Best question it answers | Best time to use | Main output | Strengths | Main limitation | Evidence base |
|---|---|---|---|---|---|---|
| Empathy map | What does one user or segment say, think, do, and feel? | Early discovery, after interviews, before ideation | Shared user-understanding artifact | Builds common ground, highlights knowledge gaps, helps prioritize needs | Can become speculative if not grounded in research | citeturn25view1 |
| Journey map | Where along the end-to-end journey do pain points, emotions, and drop-offs occur? | Acquisition, onboarding, support, renewal, cross-functional redesign | Current-state or future-state journey | Excellent for linking UX, marketing, analytics, and support data | Too-broad scope easily creates vague maps | citeturn26view0turn25view2 |
| Cognitive walkthrough | Will a new user know what to do, find the right action, and recognize progress? | New workflows, first-use experiences, major redesigns | Step-level learnability diagnosis | Strong for developers and PMs; inexpensive compared with full user testing | Best for learnability, not all UX questions | citeturn25view0 |
| Heuristic evaluation | Does the interface violate known usability principles? | Prototype stage, pre-test cleanup, complex UIs | Usability issue list by severity and principle | Fast, systematic, good for stretching research budget | Cannot replace testing with actual users | citeturn27view0turn27view1 |
| Role play | What changes when we force ourselves to speak from another perspective? | Workshops with insufficient diversity, early critique | Reframed assumptions and priorities | Useful for cross-functional teams; challenges bias and groupthink | Can feel artificial; needs a clear prompt and facilitation | citeturn25view3turn26view3 |
| Dogfooding | What breaks when we use the product in real work? | Continuous internal validation, prerelease builds | Operational issues, rough edges, adoption friction | Fast signal, good for operational empathy | Employees are not representative users; internal knowledge masks friction | citeturn35view0turn35view1turn26view0 |
| Follow-me-homes and contextual observation | What do people actually do, and why do they work around the system? | Discovery, onboarding research, problem reframing | Behavioral observations, pain points, surprises | Strong antidote to self-report bias and internal assumptions | Requires access to customers and disciplined observation | citeturn31view4turn32view1 |
For a mixed technical and non-technical audience, the best recurring pattern is usually **contextual evidence → empathy map or journey map → role-reversal critique → cognitive walkthrough or heuristic review → user validation**. That sequence is especially well suited to feature critique because it moves from broad understanding to narrow diagnosis. It also gives different functions a clear role: support and sales provide frontline signals, marketing contributes message and expectation analysis, designers frame tasks and artifacts, and developers inspect learnability, error prevention, and operational feasibility. citeturn25view1turn26view0turn25view0turn27view0turn14search16
## What to Measure
Empathy becomes actionable only when it is connected to measurement. Google’s HEART framework remains one of the most useful ways to structure product-level UX metrics because it covers **Happiness, Engagement, Adoption, Retention, and Task Success**, and pairs well with a **Goals–Signals–Metrics** process. The framework is intentionally selective: teams should not track every category mechanically, but should choose the mix that reflects the user and business problem at hand. Google later extended the same logic to developer experience, emphasizing that HEART helps teams choose what to measure rather than serving as a tool itself. citeturn20view0turn22view0
For software companies, the key analytical move is to connect **upstream** user-experience metrics to **downstream** business outcomes. NNGroup’s recent guidance draws the distinction clearly: upstream metrics tell you how the design performed, while downstream metrics indicate what changed in the business, such as support volume, conversion, or churn. That is exactly the bridge an empathy program needs. If a role-reversal review finds onboarding confusion, the resulting metrics should not stop at “users seemed confused”; they should also ask whether the redesign improved first-use completion, reduced support contacts, and improved retention or activation. citeturn23view0turn24view0
```mermaid
flowchart LR
A[Goal<br/>Help a first-time user understand and complete a feature] --> B[Signals<br/>finds feature, understands value, completes task, returns]
B --> C[UX metrics<br/>SEQ, SUS, task success, time on task, error rate]
C --> D[Behavioral metrics<br/>activation, adoption, retention]
D --> E[Business metrics<br/>conversion, support cost, churn, renewal]
```
The logic above follows Google’s Goals–Signals–Metrics model and NNGroup’s upstream-to-downstream bridge: a role-reversal review should define a concrete user goal, specify what success would look like from the user’s perspective, then connect that to metrics leadership already cares about. citeturn20view0turn23view0
The scorecard below is a rigorous but practical measurement model for feature critique.
| Evaluation question | Recommended UX metrics | Related business KPIs | Why this pairing works | Source basis |
|---|---|---|---|---|
| Is the feature understandable and learnable? | Task-success rate, error rate, time on task, SEQ, cognitive-walkthrough issue count | Support contacts, implementation friction, trial-to-activation rate | Learnability failures usually surface first as failed tasks or slow tasks, then downstream as support burden or drop-off | citeturn25view0turn24view0turn23view0turn33view0 |
| Is the feature usable overall? | SUS, ease-of-use rating, heuristic-violation count | CSAT, churn risk, post-launch rework | SUS gives a global usability benchmark; heuristics catch preventable design problems before user testing | citeturn33view1turn33view0turn27view0turn27view1 |
| Is the feature useful and valuable? | Adoption, repeat usage, retention, feature-level engagement | Conversion, renewal, expansion, churn | A usable feature can still be low-value; adoption and retention test whether the feature solves a meaningful problem | citeturn20view0turn24view0turn23view0 |
| Is the onboarding or first-run experience working? | First-use completion, time to first value, SEQ, activation rate | Trial conversion, sales-cycle efficiency, support cost | Early friction has outsized consequences for activation and retention | citeturn24view0turn23view0turn26view0 |
| Is the feature accessible and inclusive? | Accessibility issue rate, task success for diverse users, error recovery, assistive-tech compatibility | Market reach, legal and compliance risk, satisfaction | Inclusive design reduces exclusion and often improves the experience more broadly | citeturn17view0turn18view0turn31view2 |
| Is the internal delivery system supporting empathy rather than undermining it? | Developer happiness, task success on internal platforms, platform adoption, incident recovery | DORA metrics, engineering throughput, change stability | Product empathy erodes if internal tools create enough friction that teams optimize for shipping over usefulness | citeturn22view0turn21view0turn4search19 |
Where a company has internal developer platforms or design systems, it should use a second, lighter scorecard for internal users. Google Cloud’s guidance on applying HEART to developer experience is useful here: measure developer happiness, platform engagement, adoption, retention, and task success, then read those signals alongside DORA metrics such as deployment frequency, change lead time, change fail rate, failed-deployment recovery time, and deployment rework rate. DORA explicitly warns against weaponizing the metrics or comparing unlike teams; the goal is continuous improvement, not gamification. citeturn22view0turn21view0
A note on specific instruments: Brooke’s SUS remains a reliable low-cost ten-item questionnaire for overall perceived usability, and NNGroup recommends pairing short attitudinal questions such as the Single Ease Question with behavioral methods such as quantitative usability testing or analytics. That combination is usually better than relying on a single metric alone. citeturn33view1turn33view0turn24view0
## How to Embed Empathy in Process and Culture
Empathy becomes durable when it is built into process gates, review rituals, and decision rights. Human-centered-design standards already imply the core process changes: understand the context of use, specify user requirements, produce design solutions, and evaluate them iteratively with multidisciplinary involvement. In practice, that means a software company should not wait for a late-stage usability test. It should create visible checkpoints where teams explicitly ask whether a feature, message, workflow, or campaign still makes sense from the user’s viewpoint. citeturn34view0turn34view1
A good operating model for a mid-size software company is to insert empathy into four moments. First, during discovery, use direct user evidence, support data, field observation, or follow-me-homes. Second, during definition, require an empathy artifact such as an empathy map, journey map, or problem statement linked to a real persona and task. Third, during critique, run a cross-functional walkthrough on the feature, landing page, or campaign with explicit role-reversal prompts. Fourth, after release, review a compact dashboard of UX and business metrics so that the organization learns whether its empathic assumptions were valid. citeturn32view1turn25view1turn26view0turn20view0turn23view0
The role-specific pattern below is a useful way to keep empathy from remaining “owned” by design alone.
| Function | Role-reversal prompt | What this team should inspect | Typical evidence |
|---|---|---|---|
| Developers | “If I were a first-time user with no product knowledge, where would I fail or hesitate?” | Learnability, error prevention, defaults, performance blockers, operational friction, edge cases | Cognitive walkthrough, dogfooding, support tickets, logs, task-success metrics |
| Designers | “If I were this user in this context, would the interface match my language, expectations, and abilities?” | Information scent, interaction flow, accessibility, recovery from errors, emotional friction | User interviews, empathy maps, prototypes, usability tests, heuristic review |
| Sales | “If I were a buyer evaluating risk, value, and effort, what would block commitment?” | Demo flow, objection handling, implementation anxiety, trust signals, time to first value | Discovery calls, win-loss notes, onboarding friction, trial-conversion data |
| Marketing | “If I were the intended customer, would I recognize myself, understand the promise, and believe it?” | Positioning clarity, message-market fit, jargon, expectation setting, CTA friction | Journey maps, interview quotes, funnel analytics, campaign conversion and bounce patterns |
| Support and success | “Where does the product force preventable workarounds or confusion?” | Repeated pain points, failure demand, documentation gaps, friction across handoffs | Ticket themes, chat transcripts, escalation reasons, contact volume |
| Managers and leaders | “What in our process makes customer understanding difficult or optional?” | Decision latency, resourcing, review cadence, incentives, safety to surface bad news | Retrospectives, DORA trends, team surveys, roadmap churn |
This model is consistent with IBM’s view that everyone on a team should focus on users first, Microsoft’s statement that inclusive design is for program managers, engineers, data scientists, designers, and others who create products, and Intuit’s expectation that every employee improves customers’ lives through deep customer empathy. citeturn31view1turn17view0turn31view4
Barriers are predictable, and the software-engineering literature increasingly names them directly. Recent studies and syntheses in software engineering report barriers such as toxic organizational culture, workplace bias, individualistic behavior, excessive technical focus, and insufficient sustained empathy in developer-user interactions. Those findings match longstanding UX workshop experience: empathy breaks down when teams are distant from users, when the room is insufficiently diverse, or when hierarchy suppresses candid critique. citeturn8search0turn8search8turn8search20turn26view3turn25view3
The mitigation pattern is therefore both social and procedural.
| Barrier | What it looks like in a software company | Mitigation | Evidence base |
|---|---|---|---|
| Excessive technical focus | Shipping what is elegant to build rather than what is useful | Require a user task, persona, and success metric for each material feature | citeturn8search8turn20view0turn34view0 |
| Institutional-knowledge blindness | Internal experts assume customers know what the team knows | Use cognitive walkthroughs and external customer evidence; do not rely on dogfooding alone | citeturn25view0turn35view1turn26view0 |
| Low user contact | Teams build based on second-hand summaries | Bring real users into workshops when possible and expose teams to direct interviews or observation | citeturn14search16turn26view3turn32view1 |
| Weak cross-functional alignment | Product, engineering, sales, and support optimize different local goals | Use journey maps and empathy workshops to create shared language and visible tradeoffs | citeturn25view2turn26view2turn31view0 |
| Hierarchy and groupthink | Senior opinions dominate; uncomfortable feedback is softened | Facilitate workshops, allow anonymity where useful, and use role play when the room lacks diversity | citeturn25view3turn14search18turn26view3 |
| Fear of blame | Teams hide pain points or avoid early critique | Build psychological safety and blameless review practices | citeturn9search0turn31view3 |
| Emotional overload or empathy fatigue | Teams over-index on vivid anecdotes or burn out from constant affective labor | Emphasize perspective-taking, representative evidence, and bounded review rituals | citeturn7search0turn28view3turn0search12 |
Psychological safety is especially important. Google’s research on team effectiveness identifies it as a foundational ingredient of high-performing teams, and GitHub’s on-call culture notes the need for safe, blameless spaces where engineers can learn from unfamiliar situations. Empathy reviews fail when people fear that surfacing customer pain will be interpreted as incompetence or delay. citeturn9search0turn31view3
## Evidence from Software Companies
Public case evidence on empathy in software is useful, but it is uneven. The strongest public materials are often official process descriptions or commissioned studies rather than controlled field experiments. That means these cases are best used as **implementation patterns** and **directional evidence**, not as universal causal proofs. Still, taken together, they show a consistent pattern: software companies that embed empathy structurally tend to connect it to cross-functional alignment, earlier problem discovery, accessibility, and better customer experience. citeturn31view0turn31view1turn17view0turn31view2turn31view4
| Company | Public empathy practice | What the public evidence shows | What a mid-size software company can learn | Evidence quality |
|---|---|---|---|---|
| IBM | Enterprise Design Thinking | IBM frames design thinking as a user-first, scalable framework with principles of user outcomes, restless reinvention, and diverse empowered teams. IBM publicly reports faster time to market, ROI, and team-efficiency gains on its training page, clearly tying these claims to Forrester studies linked from the page. citeturn31view1turn31view0 | Give teams a common language, make user outcomes explicit, and keep design work tied to business delivery rather than isolated discovery | Moderate; official process description plus vendor-linked commissioned outcomes |
| Intuit | Design for Delight and Deep Customer Empathy | Intuit explicitly says every employee is expected to improve customers’ lives and defines D4D through Deep Customer Empathy, broad ideation, and rapid experimentation. Its method cards formalize follow-me-homes and empathy debriefs, including time boxes and prompts. citeturn31view4turn32view1turn32view0 | Treat empathy as an organizational capability, not only a design technique; make observation and debrief routine | Moderate; official methods are detailed, but quantified public outcomes are limited |
| Microsoft | Inclusive Design | Microsoft’s inclusive-design guidance centers on recognizing exclusion, learning from diversity, and solving for one then extending to many. It explicitly says the practice is for PMs, engineers, data scientists, designers, and others, and provides real-world examples like Copilot, Live Captions, Mesh Avatars, and reader tools. citeturn17view0turn18view0 | Broaden “user empathy” beyond the average user; use exclusion cases to improve mainstream experiences | Moderate; strong official practice guidance and product examples, lighter on causal metrics |
| GitHub | Accessibility shift and customer-centered operational ownership | GitHub’s public accessibility write-up emphasizes cultural shift, dedicated specialists, and permission for incremental progress. Its on-call culture case explains that ownership aligned with the code a team maintains was pursued to improve the customer experience and create a blameless, supportive culture. citeturn31view2turn31view3 | Empathy is not only front-end UX. Ownership, incident response, accessibility, and supportability are also empathy work | Moderate; strong operational narrative, limited quantified public results |
Two additional company lessons are especially practical. First, Microsoft’s official “dogfood” guidance makes clear that internal prerelease use helps teams test the newest versions and build a better experience for customers, but dogfooding works best as a **final internal check**, not as a substitute for external user evidence. Second, Atlassian’s journey-mapping guidance states the problem bluntly: even teams that use their own products every day do not necessarily use them the same ways as customers, and it is easy to assume customers share the team’s institutional knowledge. Those two observations together explain why healthy empathy programs use internal usage plus external observation, not one or the other. citeturn35view0turn26view0
The broader research on software engineering supports the case-study pattern. Recent studies in the field identify empathy as increasingly recognized but still underdeveloped in software practice, with barriers including toxic culture, bias, excessive technical focus, and weak developer-user contact. That makes the company examples above more than isolated anecdotes: they are mature responses to recurring structural problems. citeturn8search0turn8search8turn8search20turn2search19
## Practical Toolkit
The templates below are designed for direct reuse in a mid-size software company. They synthesize the report’s source base: ISO human-centered design, Google’s HEART and DORA guidance, NNGroup workshop and evaluation methods, Atlassian journey mapping, and Intuit’s deep-customer-empathy practices. citeturn34view0turn20view0turn21view0turn25view0turn25view1turn26view0turn32view1turn32view0
A practical feature-critique checklist should force teams to review **usefulness, usability, and value** separately. Many software features fail because teams collapse those into one question.
| Dimension | Review question | Evidence to inspect | Rating | Escalate if… |
|---|---|---|---|---|
| User goal | What exact task is the user trying to complete? | Persona, job-to-be-done, top task, customer quote | Green / Yellow / Red | Team cannot state the task in one sentence |
| Discoverability | Would a first-time user know where to start? | Walkthrough notes, prototype, navigation labels | Green / Yellow / Red | Users must rely on insider vocabulary |
| Learnability | Would the user know what action to take next? | Cognitive-walkthrough discussion, error-prone steps | Green / Yellow / Red | Two or more steps fail walkthrough questions |
| Usefulness | Does this solve a real pain point or only an internal idea of one? | Interview evidence, support themes, workarounds | Green / Yellow / Red | No direct evidence of pain, workaround, or unmet need |
| Usability | Can the user complete the task with low friction? | Success rate, SEQ, SUS, time on task, heuristics | Green / Yellow / Red | Success is low, time is high, or severe heuristic issues remain |
| Value | Would the user feel the outcome is worth the effort, time, or cost? | Adoption hypothesis, buyer objections, retention logic | Green / Yellow / Red | Value depends on explanation from a salesperson or onboarding specialist |
| Trust | Is the message, state, and consequence clear enough to inspire confidence? | Copy review, state feedback, error recovery | Green / Yellow / Red | Critical states are ambiguous or recovery is weak |
| Inclusion | What user group is most likely to be excluded by default? | Accessibility review, edge-case discussion | Green / Yellow / Red | Team cannot name the likely exclusion case |
| Operational empathy | If this breaks, who feels the pain first and how? | Support scenarios, incident scenarios, runbooks | Green / Yellow / Red | Support or recovery path is unclear |
| Measurement | What metric would improve if the feature truly helped? | HEART/DORA/KPI scorecard | Green / Yellow / Red | No metric is tied to the problem statement |
An empathy map template is most useful when every statement is anchored to evidence rather than intuition.
| Empathy-map field | Template prompt | Evidence source |
|---|---|---|
| Says | What has this user literally said in interviews, calls, tickets, or demos? | Direct quote or transcript |
| Thinks | What belief or concern seems to guide behavior, even if not stated directly? | Inference from observation, marked as inference |
| Does | What actions, workarounds, avoidance patterns, or repeated steps were observed? | Observation, analytics, support logs |
| Feels | What emotion is visible or credibly inferable at key moments? | Observation, sentiment line, quotes |
| Pains | What friction, risk, confusion, or cost keeps recurring? | Ticket themes, journey-map pain points |
| Gains | What outcome, reassurance, speed, or control does the user actually want? | Interviews, adoption patterns |
| Evidence gaps | What do we still not know? | Research backlog |
A user-journey critique template should connect what people experience to what teams can change.
| Journey stage | User goal | Key touchpoint | Pain point | Emotion | Current workaround | Opportunity | Owner | Metric to watch |
|---|---|---|---|---|---|---|---|---|
| Awareness | | | | | | | | |
| Evaluation | | | | | | | | |
| Trial or onboarding | | | | | | | | |
| First successful use | | | | | | | | |
| Reuse or expansion | | | | | | | | |
| Support or recovery | | | | | | | | |
For most mid-size software companies, three workshop formats are sufficient: a quick feature review, a deeper cross-functional empathy workshop, and a lightweight empathy sprint around a risky initiative. The suggested agendas below are based on Atlassian’s 90-minute journey-mapping play, NNGroup’s workshop guidance, and Intuit’s time-boxed observation and debrief methods. citeturn26view0turn26view2turn25view3turn32view1turn32view0
| Workshop format | Participants | Time | Agenda | Best use |
|---|---|---|---|---|
| Feature empathy review | PM, designer, 1–2 developers, support or sales representative, facilitator | 60–90 min | Re-state persona and task; review evidence; run cognitive walkthrough; run quick heuristic scan; assign redesign actions and metrics | A feature, release candidate, onboarding step, pricing page |
| Cross-functional empathy workshop | 4–8 people across product, design, engineering, sales, marketing, support; optional customer | 90 min | Persona and scope; build back-story; map journey; mark pain points; chart sentiment; analyze high-impact opportunities | Discovery, onboarding redesign, funnel friction |
| Lightweight empathy sprint | Cross-functional core team plus user research support | 1–2 weeks | Observe customers; debrief surprises and pain points; define problem statement; prototype; validate; prioritize by metric impact | Risky roadmap item, new audience, weak adoption, churn spike |
```mermaid
gantt
title Two-week empathy sprint
dateFormat YYYY-MM-DD
axisFormat %d %b
section Discovery
Gather support, sales, analytics evidence :a1, 2026-07-20, 2d
Follow-me-homes or contextual interviews :a2, after a1, 3d
section Synthesis
Empathy debrief and pattern clustering :b1, after a2, 1d
Problem statement and journey critique :b2, after b1, 1d
section Evaluation
Prototype or revise :c1, after b2, 2d
Role-reversal walkthrough and heuristic pass :c2, after c1, 1d
User validation and metric baseline :c3, after c2, 2d
section Decision
Go, iterate, or stop decision :d1, after c3, 1d
```
A final recommendation: keep the cadence small enough that the practice survives contact with delivery pressure. DORA warns against turning metrics into goals to be gamed, and NNGroup cautions against reporting only UX activity instead of impact. The best workshop is therefore not the most elaborate one. It is the smallest recurring ritual that still connects role-reversal to measurable change. For many software companies, that means one empathy review for every major release, one cross-functional journey workshop each quarter, and one targeted empathy sprint whenever a high-value initiative has weak user evidence. citeturn21view0turn23view0

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/0ecaa3f6-5bb3-48f5-b5f5-075d1a3655c3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/6ba4a151-50f2-46cd-a8b6-81d1002914d2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/73587b76-e4d5-4ee7-9cd1-ce1ec868d763.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/adc46f52-de83-4ab5-ad6a-06c84e7f46d8.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 KiB

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/bbe4472b-f748-4360-8293-8edacecf45bc.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/bc5ba15a-0e47-42ac-b08f-c4e05bb9bc16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 KiB

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/bf456714-fd6a-43ca-8d60-2b83b45ba92c.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/cb89efeb-0d66-40e6-97c6-43b652ea7445.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 KiB

221
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/deep-research-report (2).md

@ -0,0 +1,221 @@
# Empathy in the Workplace for Software Companies
## Executive Summary
For a mid-size software company, workplace empathy should not be treated as a soft cultural slogan. The strongest evidence supports treating it as a disciplined, human-centered practice for understanding users’ goals, constraints, emotions, mental models, and tradeoffs, then using that understanding to improve what teams build, sell, market, and support. In software work, the most operationally useful form is usually **cognitive empathy** or **perspective-taking**: the deliberate effort to understand how another person interprets a feature, message, workflow, or pricing decision. **Affective empathy** matters too, because it motivates care and ethical concern, but on its own it is less reliable as an evaluation method and can produce distress or biased judgment if it is not structured. citeturn34view0turn29view1turn29view2turn28view3turn7search0turn28view0
Human-centered design standards and guidance point in the same direction: good systems are built on an explicit understanding of users, tasks, and environments; users are involved throughout design and development; evaluation is iterative; and multidisciplinary teams participate in the work. That makes empathy a cross-functional operating principle, not just a design-team activity. Developers, designers, sales, marketing, support, and product leaders all have relevant pieces of the customer reality. citeturn34view0turn34view1
For day-to-day practice, the most effective pattern is a repeatable loop: gather direct customer evidence, synthesize it in empathy maps or journey maps, run structured role-reversal critiques on a feature or message, validate with usability inspection and user testing, then connect findings to a small balanced scorecard of UX metrics and business outcomes. Google’s HEART framework, Brooke’s SUS, task-completion measures, and DORA-style delivery metrics are complementary here: together they help teams answer whether a feature is useful, usable, valuable, and operationally healthy. citeturn20view0turn33view1turn24view0turn23view0turn21view0turn22view0
The practical implication is straightforward: a software company should institutionalize empathy as a **review discipline**. Before release, teams should ask, from the viewpoint of a real user or buyer, “Would I understand what this is for, find it, trust it, complete the task, and feel the value was worth the effort?” After release, teams should ask, “Did the evidence improve activation, task success, retention, support burden, or conversion?” That combination of role-reversal and measurement is the most defensible way to make empathy evidence-based rather than rhetorical. citeturn20view0turn24view0turn23view0turn26view0turn25view0turn27view0
The table below condenses the report’s practical recommendations into an operating model for a mid-size software company. It synthesizes ISO human-centered-design principles, Google’s HEART and DORA guidance, NNGroup methods, Atlassian workshop practices, and company examples from IBM, Intuit, Microsoft, and GitHub. citeturn34view0turn20view0turn21view0turn26view0turn31view0turn31view4turn17view0turn31view2
| Operating area | Minimum recommendation | Why it matters |
|---|---|---|
| Product and UX | Run a structured empathy review on every material feature before release | Converts assumptions into observable critique, especially for learnability and value |
| Engineering | Add cognitive walkthroughs for new workflows and dogfooding with caution | Helps expose first-time-user friction, while recognizing employees are not the same as customers |
| Sales and marketing | Review landing pages, pricing pages, demos, emails, and onboarding copy from the buyer’s perspective | Brings empathy into acquisition and expectation-setting, not only UI |
| Measurement | Track one small balanced scorecard: task success, time or effort, perceived usability, adoption or activation, retention, and one business KPI | Prevents “feel-good empathy” without outcome accountability |
| Culture and process | Involve support, research, sales, and engineering in cross-functional reviews | Broadens perspective and reduces local optimization |
| Leadership | Protect psychological safety and blameless critique | Teams cannot surface customer pain honestly if they fear blame |
## What Empathy Means in a Software Company
Empathy is not one thing. Across psychology and design research, it is commonly treated as a multidimensional construct with at least two major components. **Affective empathy** refers to sharing or resonating with another person’s feeling state. **Cognitive empathy** refers to understanding another person’s viewpoint, intentions, needs, or mental state. Related work argues that empathy and perspective-taking should be conceptually separated, because affect sharing and cognitive perspective-taking can diverge and recruit different processes. citeturn29view1turn29view2turn28view3
That distinction matters in the workplace. If a software company wants teams to evaluate features, copy, onboarding, pricing pages, or service flows by “putting themselves in the user’s shoes,” the most reliable mechanism is usually **structured perspective-taking** rather than pure emotional resonance. Perspective-taking is the cognitive process of adopting another person’s viewpoint to understand their preferences, values, and needs. Work on organizations and creativity shows that perspective-taking helps employees generate ideas that are not only novel but also useful to other people inside and outside the organization. Other research shows it can improve negotiation and creative problem solving, which is especially relevant for sales, pricing, and product tradeoff discussions. citeturn28view0turn6search8turn7search0
Affective empathy still matters, but it should be used carefully. It is often the source of prosocial concern and ethical motivation, yet it can also become empathic distress or bias attention toward vivid pain rather than representative evidence. Recent reviews distinguish empathic distress from compassion and caution that empathy can have downsides when it is unstructured or emotionally overloading. A good software-company practice is therefore to pair an affective prompt such as “What frustration or anxiety is this causing?” with cognitive prompts such as “What is the user trying to achieve, what cues do they see, and what would they reasonably infer at this step?” citeturn28view3turn29view2turn29view1
In a software firm, empathy should also be understood as **human-centered evaluation across the full customer experience**, not just interface design. ISO and NIST guidance emphasize that human-centered design addresses the whole user experience, is driven by user-centered evaluation, and requires multidisciplinary perspectives. That means developers should empathize with first-time and edge-case users, designers with user cognition and accessibility needs, sales with the buyer’s decision journey and implementation anxieties, and marketing with the customer’s information needs and language during awareness, evaluation, trial, and adoption. citeturn34view0turn34view1
The strongest practical interpretation for a software company is this: **empathy is the disciplined replacement of internal assumptions with testable, role-reversed understanding**. It is not “Would I like this?” It is “Would this specific user or buyer, in this context, with this knowledge and these constraints, understand the value, succeed at the task, and consider the result worth the cost?” That framing aligns with human-centered design, cognitive walkthroughs, and modern UX benchmarking. citeturn34view0turn25view0turn24view0
## Methods for Role Reversal and Feature Critique
A software company does not need a single empathy method. It needs a **stack** of methods, each serving a different diagnostic purpose. Empathy maps are useful for capturing what users say, think, do, and feel, and for building shared understanding. Journey maps are better for exposing end-to-end friction, especially across acquisition, onboarding, support, and renewal moments. Cognitive walkthroughs are ideal when the question is learnability for a new user. Heuristic evaluations are strong for systematic usability inspection. Role play is useful when the room lacks real users or sufficient perspective diversity. Dogfooding is valuable for surfacing operational issues rapidly, but it is incomplete because employees often have too much institutional knowledge and use the product differently than real customers. citeturn25view1turn26view0turn25view0turn27view0turn25view3turn35view1turn26view0
```mermaid
flowchart LR
A[Direct customer evidence<br/>interviews, support logs, analytics, follow-me-homes] --> B[Shared artifact<br/>empathy map or journey map]
B --> C[Role-reversal review<br/>developers, designers, sales, marketing]
C --> D[Structured critique<br/>cognitive walkthrough and heuristic evaluation]
D --> E[Prototype or revise]
E --> F[Validate with users and analytics]
F --> G[Decision<br/>ship, iterate, or stop]
G --> A
```
The workflow above reflects the common structure across ISO human-centered design, Intuit’s deep-customer-empathy methods, NNGroup workshop guidance, and Google’s Goals-Signals-Metrics logic: start from real evidence, externalize it, inspect from the other person’s perspective, then validate with measurement. citeturn34view0turn32view1turn32view0turn25view3turn20view0
The comparison below is a practical selection guide for software teams.
| Method | Best question it answers | Best time to use | Main output | Strengths | Main limitation | Evidence base |
|---|---|---|---|---|---|---|
| Empathy map | What does one user or segment say, think, do, and feel? | Early discovery, after interviews, before ideation | Shared user-understanding artifact | Builds common ground, highlights knowledge gaps, helps prioritize needs | Can become speculative if not grounded in research | citeturn25view1 |
| Journey map | Where along the end-to-end journey do pain points, emotions, and drop-offs occur? | Acquisition, onboarding, support, renewal, cross-functional redesign | Current-state or future-state journey | Excellent for linking UX, marketing, analytics, and support data | Too-broad scope easily creates vague maps | citeturn26view0turn25view2 |
| Cognitive walkthrough | Will a new user know what to do, find the right action, and recognize progress? | New workflows, first-use experiences, major redesigns | Step-level learnability diagnosis | Strong for developers and PMs; inexpensive compared with full user testing | Best for learnability, not all UX questions | citeturn25view0 |
| Heuristic evaluation | Does the interface violate known usability principles? | Prototype stage, pre-test cleanup, complex UIs | Usability issue list by severity and principle | Fast, systematic, good for stretching research budget | Cannot replace testing with actual users | citeturn27view0turn27view1 |
| Role play | What changes when we force ourselves to speak from another perspective? | Workshops with insufficient diversity, early critique | Reframed assumptions and priorities | Useful for cross-functional teams; challenges bias and groupthink | Can feel artificial; needs a clear prompt and facilitation | citeturn25view3turn26view3 |
| Dogfooding | What breaks when we use the product in real work? | Continuous internal validation, prerelease builds | Operational issues, rough edges, adoption friction | Fast signal, good for operational empathy | Employees are not representative users; internal knowledge masks friction | citeturn35view0turn35view1turn26view0 |
| Follow-me-homes and contextual observation | What do people actually do, and why do they work around the system? | Discovery, onboarding research, problem reframing | Behavioral observations, pain points, surprises | Strong antidote to self-report bias and internal assumptions | Requires access to customers and disciplined observation | citeturn31view4turn32view1 |
For a mixed technical and non-technical audience, the best recurring pattern is usually **contextual evidence → empathy map or journey map → role-reversal critique → cognitive walkthrough or heuristic review → user validation**. That sequence is especially well suited to feature critique because it moves from broad understanding to narrow diagnosis. It also gives different functions a clear role: support and sales provide frontline signals, marketing contributes message and expectation analysis, designers frame tasks and artifacts, and developers inspect learnability, error prevention, and operational feasibility. citeturn25view1turn26view0turn25view0turn27view0turn14search16
## What to Measure
Empathy becomes actionable only when it is connected to measurement. Google’s HEART framework remains one of the most useful ways to structure product-level UX metrics because it covers **Happiness, Engagement, Adoption, Retention, and Task Success**, and pairs well with a **Goals–Signals–Metrics** process. The framework is intentionally selective: teams should not track every category mechanically, but should choose the mix that reflects the user and business problem at hand. Google later extended the same logic to developer experience, emphasizing that HEART helps teams choose what to measure rather than serving as a tool itself. citeturn20view0turn22view0
For software companies, the key analytical move is to connect **upstream** user-experience metrics to **downstream** business outcomes. NNGroup’s recent guidance draws the distinction clearly: upstream metrics tell you how the design performed, while downstream metrics indicate what changed in the business, such as support volume, conversion, or churn. That is exactly the bridge an empathy program needs. If a role-reversal review finds onboarding confusion, the resulting metrics should not stop at “users seemed confused”; they should also ask whether the redesign improved first-use completion, reduced support contacts, and improved retention or activation. citeturn23view0turn24view0
```mermaid
flowchart LR
A[Goal<br/>Help a first-time user understand and complete a feature] --> B[Signals<br/>finds feature, understands value, completes task, returns]
B --> C[UX metrics<br/>SEQ, SUS, task success, time on task, error rate]
C --> D[Behavioral metrics<br/>activation, adoption, retention]
D --> E[Business metrics<br/>conversion, support cost, churn, renewal]
```
The logic above follows Google’s Goals–Signals–Metrics model and NNGroup’s upstream-to-downstream bridge: a role-reversal review should define a concrete user goal, specify what success would look like from the user’s perspective, then connect that to metrics leadership already cares about. citeturn20view0turn23view0
The scorecard below is a rigorous but practical measurement model for feature critique.
| Evaluation question | Recommended UX metrics | Related business KPIs | Why this pairing works | Source basis |
|---|---|---|---|---|
| Is the feature understandable and learnable? | Task-success rate, error rate, time on task, SEQ, cognitive-walkthrough issue count | Support contacts, implementation friction, trial-to-activation rate | Learnability failures usually surface first as failed tasks or slow tasks, then downstream as support burden or drop-off | citeturn25view0turn24view0turn23view0turn33view0 |
| Is the feature usable overall? | SUS, ease-of-use rating, heuristic-violation count | CSAT, churn risk, post-launch rework | SUS gives a global usability benchmark; heuristics catch preventable design problems before user testing | citeturn33view1turn33view0turn27view0turn27view1 |
| Is the feature useful and valuable? | Adoption, repeat usage, retention, feature-level engagement | Conversion, renewal, expansion, churn | A usable feature can still be low-value; adoption and retention test whether the feature solves a meaningful problem | citeturn20view0turn24view0turn23view0 |
| Is the onboarding or first-run experience working? | First-use completion, time to first value, SEQ, activation rate | Trial conversion, sales-cycle efficiency, support cost | Early friction has outsized consequences for activation and retention | citeturn24view0turn23view0turn26view0 |
| Is the feature accessible and inclusive? | Accessibility issue rate, task success for diverse users, error recovery, assistive-tech compatibility | Market reach, legal and compliance risk, satisfaction | Inclusive design reduces exclusion and often improves the experience more broadly | citeturn17view0turn18view0turn31view2 |
| Is the internal delivery system supporting empathy rather than undermining it? | Developer happiness, task success on internal platforms, platform adoption, incident recovery | DORA metrics, engineering throughput, change stability | Product empathy erodes if internal tools create enough friction that teams optimize for shipping over usefulness | citeturn22view0turn21view0turn4search19 |
Where a company has internal developer platforms or design systems, it should use a second, lighter scorecard for internal users. Google Cloud’s guidance on applying HEART to developer experience is useful here: measure developer happiness, platform engagement, adoption, retention, and task success, then read those signals alongside DORA metrics such as deployment frequency, change lead time, change fail rate, failed-deployment recovery time, and deployment rework rate. DORA explicitly warns against weaponizing the metrics or comparing unlike teams; the goal is continuous improvement, not gamification. citeturn22view0turn21view0
A note on specific instruments: Brooke’s SUS remains a reliable low-cost ten-item questionnaire for overall perceived usability, and NNGroup recommends pairing short attitudinal questions such as the Single Ease Question with behavioral methods such as quantitative usability testing or analytics. That combination is usually better than relying on a single metric alone. citeturn33view1turn33view0turn24view0
## How to Embed Empathy in Process and Culture
Empathy becomes durable when it is built into process gates, review rituals, and decision rights. Human-centered-design standards already imply the core process changes: understand the context of use, specify user requirements, produce design solutions, and evaluate them iteratively with multidisciplinary involvement. In practice, that means a software company should not wait for a late-stage usability test. It should create visible checkpoints where teams explicitly ask whether a feature, message, workflow, or campaign still makes sense from the user’s viewpoint. citeturn34view0turn34view1
A good operating model for a mid-size software company is to insert empathy into four moments. First, during discovery, use direct user evidence, support data, field observation, or follow-me-homes. Second, during definition, require an empathy artifact such as an empathy map, journey map, or problem statement linked to a real persona and task. Third, during critique, run a cross-functional walkthrough on the feature, landing page, or campaign with explicit role-reversal prompts. Fourth, after release, review a compact dashboard of UX and business metrics so that the organization learns whether its empathic assumptions were valid. citeturn32view1turn25view1turn26view0turn20view0turn23view0
The role-specific pattern below is a useful way to keep empathy from remaining “owned” by design alone.
| Function | Role-reversal prompt | What this team should inspect | Typical evidence |
|---|---|---|---|
| Developers | “If I were a first-time user with no product knowledge, where would I fail or hesitate?” | Learnability, error prevention, defaults, performance blockers, operational friction, edge cases | Cognitive walkthrough, dogfooding, support tickets, logs, task-success metrics |
| Designers | “If I were this user in this context, would the interface match my language, expectations, and abilities?” | Information scent, interaction flow, accessibility, recovery from errors, emotional friction | User interviews, empathy maps, prototypes, usability tests, heuristic review |
| Sales | “If I were a buyer evaluating risk, value, and effort, what would block commitment?” | Demo flow, objection handling, implementation anxiety, trust signals, time to first value | Discovery calls, win-loss notes, onboarding friction, trial-conversion data |
| Marketing | “If I were the intended customer, would I recognize myself, understand the promise, and believe it?” | Positioning clarity, message-market fit, jargon, expectation setting, CTA friction | Journey maps, interview quotes, funnel analytics, campaign conversion and bounce patterns |
| Support and success | “Where does the product force preventable workarounds or confusion?” | Repeated pain points, failure demand, documentation gaps, friction across handoffs | Ticket themes, chat transcripts, escalation reasons, contact volume |
| Managers and leaders | “What in our process makes customer understanding difficult or optional?” | Decision latency, resourcing, review cadence, incentives, safety to surface bad news | Retrospectives, DORA trends, team surveys, roadmap churn |
This model is consistent with IBM’s view that everyone on a team should focus on users first, Microsoft’s statement that inclusive design is for program managers, engineers, data scientists, designers, and others who create products, and Intuit’s expectation that every employee improves customers’ lives through deep customer empathy. citeturn31view1turn17view0turn31view4
Barriers are predictable, and the software-engineering literature increasingly names them directly. Recent studies and syntheses in software engineering report barriers such as toxic organizational culture, workplace bias, individualistic behavior, excessive technical focus, and insufficient sustained empathy in developer-user interactions. Those findings match longstanding UX workshop experience: empathy breaks down when teams are distant from users, when the room is insufficiently diverse, or when hierarchy suppresses candid critique. citeturn8search0turn8search8turn8search20turn26view3turn25view3
The mitigation pattern is therefore both social and procedural.
| Barrier | What it looks like in a software company | Mitigation | Evidence base |
|---|---|---|---|
| Excessive technical focus | Shipping what is elegant to build rather than what is useful | Require a user task, persona, and success metric for each material feature | citeturn8search8turn20view0turn34view0 |
| Institutional-knowledge blindness | Internal experts assume customers know what the team knows | Use cognitive walkthroughs and external customer evidence; do not rely on dogfooding alone | citeturn25view0turn35view1turn26view0 |
| Low user contact | Teams build based on second-hand summaries | Bring real users into workshops when possible and expose teams to direct interviews or observation | citeturn14search16turn26view3turn32view1 |
| Weak cross-functional alignment | Product, engineering, sales, and support optimize different local goals | Use journey maps and empathy workshops to create shared language and visible tradeoffs | citeturn25view2turn26view2turn31view0 |
| Hierarchy and groupthink | Senior opinions dominate; uncomfortable feedback is softened | Facilitate workshops, allow anonymity where useful, and use role play when the room lacks diversity | citeturn25view3turn14search18turn26view3 |
| Fear of blame | Teams hide pain points or avoid early critique | Build psychological safety and blameless review practices | citeturn9search0turn31view3 |
| Emotional overload or empathy fatigue | Teams over-index on vivid anecdotes or burn out from constant affective labor | Emphasize perspective-taking, representative evidence, and bounded review rituals | citeturn7search0turn28view3turn0search12 |
Psychological safety is especially important. Google’s research on team effectiveness identifies it as a foundational ingredient of high-performing teams, and GitHub’s on-call culture notes the need for safe, blameless spaces where engineers can learn from unfamiliar situations. Empathy reviews fail when people fear that surfacing customer pain will be interpreted as incompetence or delay. citeturn9search0turn31view3
## Evidence from Software Companies
Public case evidence on empathy in software is useful, but it is uneven. The strongest public materials are often official process descriptions or commissioned studies rather than controlled field experiments. That means these cases are best used as **implementation patterns** and **directional evidence**, not as universal causal proofs. Still, taken together, they show a consistent pattern: software companies that embed empathy structurally tend to connect it to cross-functional alignment, earlier problem discovery, accessibility, and better customer experience. citeturn31view0turn31view1turn17view0turn31view2turn31view4
| Company | Public empathy practice | What the public evidence shows | What a mid-size software company can learn | Evidence quality |
|---|---|---|---|---|
| IBM | Enterprise Design Thinking | IBM frames design thinking as a user-first, scalable framework with principles of user outcomes, restless reinvention, and diverse empowered teams. IBM publicly reports faster time to market, ROI, and team-efficiency gains on its training page, clearly tying these claims to Forrester studies linked from the page. citeturn31view1turn31view0 | Give teams a common language, make user outcomes explicit, and keep design work tied to business delivery rather than isolated discovery | Moderate; official process description plus vendor-linked commissioned outcomes |
| Intuit | Design for Delight and Deep Customer Empathy | Intuit explicitly says every employee is expected to improve customers’ lives and defines D4D through Deep Customer Empathy, broad ideation, and rapid experimentation. Its method cards formalize follow-me-homes and empathy debriefs, including time boxes and prompts. citeturn31view4turn32view1turn32view0 | Treat empathy as an organizational capability, not only a design technique; make observation and debrief routine | Moderate; official methods are detailed, but quantified public outcomes are limited |
| Microsoft | Inclusive Design | Microsoft’s inclusive-design guidance centers on recognizing exclusion, learning from diversity, and solving for one then extending to many. It explicitly says the practice is for PMs, engineers, data scientists, designers, and others, and provides real-world examples like Copilot, Live Captions, Mesh Avatars, and reader tools. citeturn17view0turn18view0 | Broaden “user empathy” beyond the average user; use exclusion cases to improve mainstream experiences | Moderate; strong official practice guidance and product examples, lighter on causal metrics |
| GitHub | Accessibility shift and customer-centered operational ownership | GitHub’s public accessibility write-up emphasizes cultural shift, dedicated specialists, and permission for incremental progress. Its on-call culture case explains that ownership aligned with the code a team maintains was pursued to improve the customer experience and create a blameless, supportive culture. citeturn31view2turn31view3 | Empathy is not only front-end UX. Ownership, incident response, accessibility, and supportability are also empathy work | Moderate; strong operational narrative, limited quantified public results |
Two additional company lessons are especially practical. First, Microsoft’s official “dogfood” guidance makes clear that internal prerelease use helps teams test the newest versions and build a better experience for customers, but dogfooding works best as a **final internal check**, not as a substitute for external user evidence. Second, Atlassian’s journey-mapping guidance states the problem bluntly: even teams that use their own products every day do not necessarily use them the same ways as customers, and it is easy to assume customers share the team’s institutional knowledge. Those two observations together explain why healthy empathy programs use internal usage plus external observation, not one or the other. citeturn35view0turn26view0
The broader research on software engineering supports the case-study pattern. Recent studies in the field identify empathy as increasingly recognized but still underdeveloped in software practice, with barriers including toxic culture, bias, excessive technical focus, and weak developer-user contact. That makes the company examples above more than isolated anecdotes: they are mature responses to recurring structural problems. citeturn8search0turn8search8turn8search20turn2search19
## Practical Toolkit
The templates below are designed for direct reuse in a mid-size software company. They synthesize the report’s source base: ISO human-centered design, Google’s HEART and DORA guidance, NNGroup workshop and evaluation methods, Atlassian journey mapping, and Intuit’s deep-customer-empathy practices. citeturn34view0turn20view0turn21view0turn25view0turn25view1turn26view0turn32view1turn32view0
A practical feature-critique checklist should force teams to review **usefulness, usability, and value** separately. Many software features fail because teams collapse those into one question.
| Dimension | Review question | Evidence to inspect | Rating | Escalate if… |
|---|---|---|---|---|
| User goal | What exact task is the user trying to complete? | Persona, job-to-be-done, top task, customer quote | Green / Yellow / Red | Team cannot state the task in one sentence |
| Discoverability | Would a first-time user know where to start? | Walkthrough notes, prototype, navigation labels | Green / Yellow / Red | Users must rely on insider vocabulary |
| Learnability | Would the user know what action to take next? | Cognitive-walkthrough discussion, error-prone steps | Green / Yellow / Red | Two or more steps fail walkthrough questions |
| Usefulness | Does this solve a real pain point or only an internal idea of one? | Interview evidence, support themes, workarounds | Green / Yellow / Red | No direct evidence of pain, workaround, or unmet need |
| Usability | Can the user complete the task with low friction? | Success rate, SEQ, SUS, time on task, heuristics | Green / Yellow / Red | Success is low, time is high, or severe heuristic issues remain |
| Value | Would the user feel the outcome is worth the effort, time, or cost? | Adoption hypothesis, buyer objections, retention logic | Green / Yellow / Red | Value depends on explanation from a salesperson or onboarding specialist |
| Trust | Is the message, state, and consequence clear enough to inspire confidence? | Copy review, state feedback, error recovery | Green / Yellow / Red | Critical states are ambiguous or recovery is weak |
| Inclusion | What user group is most likely to be excluded by default? | Accessibility review, edge-case discussion | Green / Yellow / Red | Team cannot name the likely exclusion case |
| Operational empathy | If this breaks, who feels the pain first and how? | Support scenarios, incident scenarios, runbooks | Green / Yellow / Red | Support or recovery path is unclear |
| Measurement | What metric would improve if the feature truly helped? | HEART/DORA/KPI scorecard | Green / Yellow / Red | No metric is tied to the problem statement |
An empathy map template is most useful when every statement is anchored to evidence rather than intuition.
| Empathy-map field | Template prompt | Evidence source |
|---|---|---|
| Says | What has this user literally said in interviews, calls, tickets, or demos? | Direct quote or transcript |
| Thinks | What belief or concern seems to guide behavior, even if not stated directly? | Inference from observation, marked as inference |
| Does | What actions, workarounds, avoidance patterns, or repeated steps were observed? | Observation, analytics, support logs |
| Feels | What emotion is visible or credibly inferable at key moments? | Observation, sentiment line, quotes |
| Pains | What friction, risk, confusion, or cost keeps recurring? | Ticket themes, journey-map pain points |
| Gains | What outcome, reassurance, speed, or control does the user actually want? | Interviews, adoption patterns |
| Evidence gaps | What do we still not know? | Research backlog |
A user-journey critique template should connect what people experience to what teams can change.
| Journey stage | User goal | Key touchpoint | Pain point | Emotion | Current workaround | Opportunity | Owner | Metric to watch |
|---|---|---|---|---|---|---|---|---|
| Awareness | | | | | | | | |
| Evaluation | | | | | | | | |
| Trial or onboarding | | | | | | | | |
| First successful use | | | | | | | | |
| Reuse or expansion | | | | | | | | |
| Support or recovery | | | | | | | | |
For most mid-size software companies, three workshop formats are sufficient: a quick feature review, a deeper cross-functional empathy workshop, and a lightweight empathy sprint around a risky initiative. The suggested agendas below are based on Atlassian’s 90-minute journey-mapping play, NNGroup’s workshop guidance, and Intuit’s time-boxed observation and debrief methods. citeturn26view0turn26view2turn25view3turn32view1turn32view0
| Workshop format | Participants | Time | Agenda | Best use |
|---|---|---|---|---|
| Feature empathy review | PM, designer, 1–2 developers, support or sales representative, facilitator | 60–90 min | Re-state persona and task; review evidence; run cognitive walkthrough; run quick heuristic scan; assign redesign actions and metrics | A feature, release candidate, onboarding step, pricing page |
| Cross-functional empathy workshop | 4–8 people across product, design, engineering, sales, marketing, support; optional customer | 90 min | Persona and scope; build back-story; map journey; mark pain points; chart sentiment; analyze high-impact opportunities | Discovery, onboarding redesign, funnel friction |
| Lightweight empathy sprint | Cross-functional core team plus user research support | 1–2 weeks | Observe customers; debrief surprises and pain points; define problem statement; prototype; validate; prioritize by metric impact | Risky roadmap item, new audience, weak adoption, churn spike |
```mermaid
gantt
title Two-week empathy sprint
dateFormat YYYY-MM-DD
axisFormat %d %b
section Discovery
Gather support, sales, analytics evidence :a1, 2026-07-20, 2d
Follow-me-homes or contextual interviews :a2, after a1, 3d
section Synthesis
Empathy debrief and pattern clustering :b1, after a2, 1d
Problem statement and journey critique :b2, after b1, 1d
section Evaluation
Prototype or revise :c1, after b2, 2d
Role-reversal walkthrough and heuristic pass :c2, after c1, 1d
User validation and metric baseline :c3, after c2, 2d
section Decision
Go, iterate, or stop decision :d1, after c3, 1d
```
A final recommendation: keep the cadence small enough that the practice survives contact with delivery pressure. DORA warns against turning metrics into goals to be gamed, and NNGroup cautions against reporting only UX activity instead of impact. The best workshop is therefore not the most elaborate one. It is the smallest recurring ritual that still connects role-reversal to measurable change. For many software companies, that means one empathy review for every major release, one cross-functional journey workshop each quarter, and one targeted empathy sprint whenever a high-value initiative has weak user evidence. citeturn21view0turn23view0

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v1/wearedevelopers-world-congress-2026-berlin-ticket-D4CZ-1.pdf

Binary file not shown.

96
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/empathy-in-the-workplace.md

@ -0,0 +1,96 @@
# Empathy in the Workplace for Software Companies
![Empathy at work: a cross-functional software team discussing who they are building for](images/hero.png)
Great software is not created only through clean code, attractive interfaces, persuasive campaigns, or polished sales demonstrations. It is created when teams understand the people behind the requirements: what users are trying to achieve, what they already know, what confuses them, and what they consider valuable.
For a software company, empathy should not be treated as a soft cultural slogan. It is a disciplined practice for replacing internal assumptions with evidence about users, buyers, administrators, developers, and other people affected by the product.
## What Empathy Means in a Software Company
![Why empathy matters in software development](images/why-empathy.png)
Empathy includes both emotional concern and perspective-taking. In product work, the most actionable form is often cognitive empathy: deliberately examining a feature, workflow, message, or pricing decision from another person’s point of view.
> **The useful question is not:** “Would I like this?”
> **It is:** “Would this specific user, in this context, with this knowledge and these constraints, understand the value and complete the task?”
This distinction matters because employees possess institutional knowledge that customers do not. A flow that feels obvious to the product team may be unclear to a first-time user. A message that sounds precise to engineering may sound like jargon to a buyer. A feature that is easy to demonstrate may still be difficult to adopt in a real organization.
## Empathy Is a Cross-Functional Responsibility
![Empathy questions for developers, designers, sales, marketing, and the wider team](images/roles.png)
Empathy cannot remain owned only by product designers. Every function sees a different part of the customer reality:
| Function | Perspective-taking question | What to inspect |
|---|---|---|
| Developers | Where would a first-time user fail, hesitate, or misunderstand the system? | Defaults, errors, performance, learnability, edge cases, operational friction |
| Designers | Does the interface match the user’s language, expectations, abilities, and context? | Information architecture, accessibility, cognitive load, recovery from mistakes |
| Sales | What would make a buyer doubt the value, risk, implementation effort, or credibility? | Demo flow, objections, trust signals, time to value, organizational anxiety |
| Marketing | Would the intended customer recognize their problem and believe the promise? | Positioning, jargon, expectation setting, calls to action, message-market fit |
| Support and success | Where does the product repeatedly create avoidable confusion or workarounds? | Ticket themes, escalations, documentation gaps, recurring failure patterns |
## A Practical Empathy Loop
![Six-stage empathy loop: understand, empathize, define, create, validate, repeat](images/empathy-loop.png)
A reliable empathy practice begins with real evidence and ends with validation. The process can be kept simple:
1. **Understand:** Talk to users, observe them, review support conversations, and study behavioral data.
2. **Empathize:** Identify goals, fears, limitations, mental models, and environmental constraints.
3. **Define:** Frame the problem from the user’s viewpoint rather than the product’s internal structure.
4. **Create:** Design and build with that user context visible to the team.
5. **Validate:** Test assumptions with users and measurable outcomes.
6. **Repeat:** Treat empathy as an ongoing operating habit, not a workshop completed once.
## Methods for Role Reversal and Feature Critique
Different questions require different methods. Empathy maps help teams distinguish what users say, think, do, and feel. Journey maps reveal friction across acquisition, onboarding, support, and renewal. Cognitive walkthroughs test whether a new user can discover the correct action and recognize progress. Heuristic reviews expose systematic usability problems. Contextual observation reveals what people actually do rather than what they remember doing.
Dogfooding is useful, but it is not sufficient. Employees usually know too much about the product, understand its vocabulary, and forgive rough edges that genuine customers may not tolerate. Internal usage should therefore supplement—not replace—external user evidence.
## Putting Empathy into Daily Practice
![Practical empathy checklist for software teams](images/practice.png)
Empathy becomes durable when it is built into ordinary delivery rituals. A team can begin with a few lightweight practices:
- Bring real customer feedback into planning and refinement sessions.
- Watch users attempt important tasks without coaching them.
- Ask what would frustrate, confuse, or reduce trust at each step.
- Review important work as though encountering the product for the first time.
- Include product, engineering, design, sales, marketing, and support in selected critiques.
- Connect findings to activation, task success, adoption, retention, conversion, support volume, or churn.
![Empathy is about building the right thing for the right people in the right way](images/quote.png)
## Measure Whether Empathy Changes Outcomes
Empathy should produce testable hypotheses. When a team identifies onboarding confusion, it should define what improvement would look like: higher first-use completion, shorter time to value, fewer support contacts, or stronger activation and retention.
A balanced scorecard can combine behavioral and attitudinal evidence:
- Task-success and error rates
- Time or effort required to complete a task
- Perceived ease of use and overall usability
- Activation, adoption, repeat use, and retention
- Support demand, conversion, renewal, and churn
The goal is not to turn empathy into a single number. The goal is to ensure that teams learn whether their understanding of the user was accurate.
## Create the Conditions for Honest Critique
Empathy reviews fail when teams fear blame, senior opinions dominate the room, or technical elegance consistently outweighs user value. Leaders should protect psychological safety, invite uncomfortable evidence, and treat surfaced friction as useful information rather than personal criticism.
Teams should also avoid over-indexing on vivid anecdotes. A powerful customer story can reveal an important problem, but decisions should be checked against representative research, usage data, and business context.
---
![Better empathy, better software](images/closing.png)
## Better Empathy, Better Software
Empathy is not simply about being nice. In a software company, it means building the right thing, for the right people, in the right way. It helps developers anticipate failure, designers reduce cognitive friction, sales teams understand buyer risk, marketers communicate in the customer’s language, and leaders create systems that reward learning rather than assumption.
When teams consistently ask how their work will be understood, used, trusted, and valued by the people on the other side of the screen, they build products they can be proud to use, recommend, and stand behind.

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/closing.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 KiB

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/empathy-loop.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 KiB

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/hero.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/practice.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/quote.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/roles.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
docs/en/Community-Articles/2026-07-17-Empathy-At-Work/draft/v2/images/why-empathy.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

64
docs/en/Community-Articles/2026-07-17-WAD-RECAP/post.md

@ -0,0 +1,64 @@
<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Poppins, sans-serif;"><span style="font-size: 11pt;">WeAreDevelopers World Congress 2026 has come to an end, and we'd like to thank everyone who stopped by the ABP booth in Berlin!</span></span></span></span>
<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Poppins, sans-serif;"><span style="font-size: 11pt;">We had the opportunity to meet developers, architects, engineering leaders, and technology enthusiasts from around the world. It was a pleasure connecting with so many members of the developer community, hearing about the projects you're building, and discussing the challenges and opportunities shaping modern software development.</span></span></span></span>
![ABP team at WeAreDevelopers World Congress 2026.1](https://abp.io/api/file-management/file-descriptor/share?shareToken=CfDJ8BFJWl%2BAUE9Cj%2FpQ216BBS4zHy%2BR4dF3%2BYf%2FtQCpm6USG%2BPfkEFUE0giWmqZzA%2FqHbedsADTkW5jxPZVxyJjD1ZxYkCFVpgySB8KSYBTBAdDql%2FEFmCA8GZ7%2F1p0W2Y5V2ob%2F5I77rotPvY3K2lPaKkH4WPQnNbou02%2BJVW6wPxN)
![ABP team at WeAreDevelopers World Congress 2026.2](https://abp.io/api/file-management/file-descriptor/share?shareToken=CfDJ8BFJWl%2BAUE9Cj%2FpQ216BBS69OYPeQbcVnawHZSL4ohAgZW3zQ%2BLnKM2ZJcj3mVMXlqXqyI7JQNCfbjJODmfRzdEaEyjXI2Afgx4q9gnOTM%2F8jfISltQ%2FhJIlLt8cyKzG4t%2FLWhjP4K0olwpw2AxU1FHx30pKKKb03NCGPF%2BXoq67)
## **<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Lexend, sans-serif;"><span style="font-size: 17pt;">Great Conversations and Product Demos</span></span></span></span>**
<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Poppins, sans-serif;"><span style="font-size: 11pt;">Throughout the event, our team showcased the latest developments across the ABP ecosystem, including ABP Framework, ABP Studio, and our AI-powered development capabilities.</span></span></span></span>
<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Poppins, sans-serif;"><span style="font-size: 11pt;">We had countless conversations about modular application development, clean architecture, microservices, AI-assisted development, and how teams can build enterprise applications faster while maintaining long-term quality and maintainability.</span></span></span></span>
<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Poppins, sans-serif;"><span style="font-size: 11pt;">Thank you to everyone who shared feedback, asked questions, and explored how ABP can support your development journey.</span></span></span></span>
![ABP team at WeAreDevelopers World Congress 2026.3](https://abp.io/api/file-management/file-descriptor/share?shareToken=CfDJ8BFJWl%2BAUE9Cj%2FpQ216BBS5Lh7%2Fs%2BJm9dBfa89UIM8DtdlERFkfiUAx2DzqxE0v8z5hf%2BDWpFiiYVOjWq5NTdFxaqqzM079kwIYLEGcL7LljvWtjm5EZtbFYBlqXt8P4stnEmMSclaZocHZp4OgS%2BfN0caba4RQpLQgjIESBICFU)
![ABP team at WeAreDevelopers World Congress 2026.4](https://abp.io/api/file-management/file-descriptor/share?shareToken=CfDJ8BFJWl%2BAUE9Cj%2FpQ216BBS4MxSzQqrl5ZNL%2BYgzHUxeTjm0uv%2B68PDOkP8P%2BwVJeSiVYFwsyumyB2tI85Ik5nJMbWt5zzaOHUUhYKKSHFZMRg4uAcAVSyT9hIdF3G3DeN6lfzCraFeA7SOvbgPTSiho6VxgzIndricFCd6bfMleD)
## **<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Lexend, sans-serif;"><span style="font-size: 17pt;">Sharing Our Experience on Stage</span></span></span></span>**
In addition to connecting with attendees at our booth, we were proud to see our Co-founder, **Halil İbrahim Kalkan**, speak at WeAreDevelopers World Congress 2026.
His session, **"Dynamic Entities in .NET: Building Low-Code Systems on Top of Entity Framework Core"** explored how developers can build flexible, dynamic applications while leveraging the power of Entity Framework Core and the .NET ecosystem.
It was a great opportunity to share the engineering practices and ideas behind ABP with the wider developer community. Thank you to everyone who attended the session and joined the discussion.
![ABP team at WeAreDevelopers World Congress 2026.5](https://abp.io/api/file-management/file-descriptor/share?shareToken=CfDJ8BFJWl%2BAUE9Cj%2FpQ216BBS6o2J%2FNrkCu8kKnfIGPt4h9zpeS61T2EHZ76ICCnBJlBMiQbXHWjHfPa7ZrWWmSA8om%2F5%2FPGUtcVR9yeGXj7jckumTHqSk1hTDQLDrs8pyYs4K1hz3FOpDmsNo8DBxaf8BDBtYY8RnfSMjUuhTiTMVn)
## **<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Lexend, sans-serif;"><span style="font-size: 17pt;">More Than Just a Conference</span></span></span></span>**
<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Poppins, sans-serif;"><span style="font-size: 11pt;">WeAreDevelopers World Congress wasn't only about technical sessions. The event also featured interactive experiences, including a lively arcade gaming area, creating plenty of opportunities for attendees to relax, connect, and enjoy the conference between talks.</span></span></span></span>
<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Poppins, sans-serif;"><span style="font-size: 11pt;">This is the approach I'd recommend. It keeps the ABP story focused while giving you a natural place to include photos or videos of the arcade area.</span></span></span></span>
[![Watch the Gaming Area video on YouTube](https://abp.io/api/file-management/file-descriptor/share?shareToken=CfDJ8BFJWl%2BAUE9Cj%2FpQ216BBS7Zcq8bydK7%2BRRT0moIRkCgYSX6gkXffggpSCpS7%2B%2BZQuC42apGawV4nYr%2FKDuY7UHtlw7AbIFV5cIIevx2UqQ1IPG%2Bp4IWeYKH0isSwi0Jk36jBkH21UQiNlUFnif38Cd8copX22EX1eGV0DGpwjId)](https://youtu.be/K2WzoMfO76k)
![ABP team at WeAreDevelopers World Congress 2026.7](https://abp.io/api/file-management/file-descriptor/share?shareToken=CfDJ8BFJWl%2BAUE9Cj%2FpQ216BBS5E2azupUQeKZCFpz8uOxJfDT%2BoD%2B6sKWEDVrQZLKPgwWauQman6CjAA35QPNHDPaR89CJNnOaqAr%2BDVZNUF5LLpqtkkbhDxL8cs19hRvOozR%2B%2FEMDMLQv05ZicCEswkaH68pIi8Htau91x2j%2B%2FZUNY)
## **<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Lexend, sans-serif;"><span style="font-size: 17pt;">Meeting The Developer Community</span></span></span></span>**
<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Poppins, sans-serif;"><span style="font-size: 11pt;">One of the best parts of WeAreDevelopers World Congress is bringing together developers, architects, engineering leaders, and technology experts from around the world. The conference featured inspiring keynotes and technical sessions covering AI, software architecture, cloud, developer productivity, and many other topics that are shaping the future of software development.</span></span></span></span>
![ABP team at WeAreDevelopers World Congress 2026.8](https://abp.io/api/file-management/file-descriptor/share?shareToken=CfDJ8BFJWl%2BAUE9Cj%2FpQ216BBS4sS8dtDS3uz8BQ08GHrJhfYezTNm7iIPkGxmwSzAdqu3I5Xm83qEuWbyZyrkz%2FexjK%2BqWZ%2BwC2eUpOcjNJPk7a4RM97Es6Yy1SVC1k08fcpqmbF22enrV9%2FCRwLRaA0693i9TAlo1NBOcQAGDDLgfx)
![ABP team at WeAreDevelopers World Congress 2026.10](https://abp.io/api/file-management/file-descriptor/share?shareToken=CfDJ8BFJWl%2BAUE9Cj%2FpQ216BBS6R8ZtcNmxyjBlV%2Fqiov6VfF0%2Fz9bl4VCdmSDfkDK%2Bmx8dmbrxOiiw8bIfymVWjEbIw9wzujp0R90K%2FgC7s3n7UaPSROiKcLwOBms3JB8To9G3wywNHRC3uKOLiFdszXLwNyZmqRemsUm5%2FTXTfAzy5)
![ABP team at WeAreDevelopers World Congress 2026.11](https://abp.io/api/file-management/file-descriptor/share?shareToken=CfDJ8BFJWl%2BAUE9Cj%2FpQ216BBS7FG5qcTtOkfnSg7C9sq9zTrhQ%2FlW5Qe3YPb1WUnp6Yg%2BSXIPdg8B7L%2BiAtW7wqVK6%2FLU3EFpxIlEA1zYa23xwlggpo6V8%2BWFppT88NGxQ5Kn6vBV8S2vX1rytjS7RUjBHVXxJR8X5Vk49WYv5kCER9)
## **<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Lexend, sans-serif;"><span style="font-size: 17pt;">Until Next Time</span></span></span></span>**
<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Poppins, sans-serif;"><span style="font-size: 11pt;">A big thank you to the WeAreDevelopers team for organizing another fantastic event and to everyone who visited us at Hall A, Booth A-41.</span></span></span></span>
<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Poppins, sans-serif;"><span style="font-size: 11pt;">If we didn't get the chance to meet in Berlin, you can always explore ABP online, join our community, or reach out to us with your questions and feedback.</span></span></span></span>
<span style="background-color: transparent;"><span style="color: rgb(0, 0, 0);"><span style="font-family: Poppins, sans-serif;"><span style="font-size: 11pt;">We appreciate everyone who made WeAreDevelopers World Congress 2026 such a memorable experience, and we look forward to seeing you again at future events!</span></span></span></span>
​
![ABP team at WeAreDevelopers World Congress 2026.12](https://abp.io/api/file-management/file-descriptor/share?shareToken=CfDJ8BFJWl%2BAUE9Cj%2FpQ216BBS60ifxXi0WKAOMXk3uWgymwuMfSRR441sbaecJaHrzvlKokwVAQHsFtcr%2ByT9WJlUME5VTvE3iny0Rx9tVmSqlKRfKrAgvsEsyl1ACFjqjUvzqlXvswIpLWXNxoqIm%2BGylB6JFSA1cASNXNIs21tq9P)
![ABP team at WeAreDevelopers World Congress 2026.13](https://abp.io/api/file-management/file-descriptor/share?shareToken=CfDJ8BFJWl%2BAUE9Cj%2FpQ216BBS734IO%2BudVyD2%2FGzg7qP1XkRTg7ZT5zZ2pLv5%2FoDqvo8sB%2FGEfkshjTmD0YBjDCeWKrpTHI6pK1TEIg%2FQoMX6SGoudWzymr2pQMFpzF2ATCE%2FdB3XRNSITLSaS6L40V8UfryzP8DBjDwlNizxPI5tGw)
​

2
docs/en/framework/api-development/auto-controllers.md

@ -62,6 +62,8 @@ ABP uses a naming convention while determining the HTTP method for a service met
If you need to customize HTTP method for a particular method, then you can use one of the standard ASP.NET Core attributes ([HttpPost], [HttpGet], [HttpPut]... etc.). This requires to add [Microsoft.AspNetCore.Mvc.Core](https://www.nuget.org/packages/Microsoft.AspNetCore.Mvc.Core) nuget package to your project that contains the service.
The naming convention doesn't map the HTTP QUERY method (a safe method that carries its parameters in the request body, useful when a GET request would have too many query string parameters). If you want to expose an action as a QUERY endpoint, use the `[AcceptVerbs("QUERY")]` attribute explicitly. Such an action is treated as a safe method, so it is not audited and doesn't start a transactional unit of work by default, just like a GET request. However, unlike a GET request, a QUERY request still requires the anti-forgery token because it carries a request body. This is consistent with ASP.NET Core, which doesn't treat QUERY as an anti-forgery exempt method.
### Route
Route is calculated based on some conventions:

4
docs/en/framework/architecture/domain-driven-design/unit-of-work.md

@ -38,10 +38,10 @@ All of these are automatically handled by the ABP.
While the section above explains the UOW as it is database transaction, actually a UOW doesn't have to be transactional. By default;
* **HTTP GET** requests don't start a transactional UOW. They still starts a UOW, but **doesn't create a database transaction**.
* **HTTP GET** and **HTTP QUERY** requests don't start a transactional UOW. They still start a UOW, but **don't create a database transaction**.
* All other HTTP request types start a UOW with a database transaction, if database level transactions are supported by the underlying database provider.
This is because an HTTP GET request doesn't (and shouldn't) make any change in the database. You can change this behavior using the options explained below.
This is because they are safe HTTP methods that don't (and shouldn't) make any change in the database. You can change this behavior using the options explained below.
## Default Options

2
docs/en/framework/infrastructure/audit-logging.md

@ -48,7 +48,7 @@ Here, a list of the options you can configure:
* `IsEnabledForAnonymousUsers` (default: `true`): If you want to write audit logs only for the authenticated users, set this to `false`. If you save audit logs for anonymous users, you will see `null` for `UserId` values for these users.
* `AlwaysLogOnException` (default: `true`): If you set to true, it always saves the audit log on an exception/error case without checking other options (except `IsEnabled`, which completely disables the audit logging).
* `IsEnabledForIntegrationServices` (default: `false`): Audit Logging is disabled for [integration services](../api-development/integration-services.md) by default. Set this property as `true` to enable it.
* `IsEnabledForGetRequests` (default: `false`): HTTP GET requests should not make any change in the database normally and audit log system doesn't save audit log objects for GET request. Set this to `true` to enable it also for the GET requests.
* `IsEnabledForGetRequests` (default: `false`): Safe HTTP methods (GET, HEAD and QUERY) should not make any change in the database normally and the audit log system doesn't save audit log objects for these requests. Set this to `true` to enable it also for the safe requests.
* `DisableLogActionInfo` (default: `false`):If you set to true, Will no longer log `AuditLogActionInfo`.
* `ApplicationName`: If multiple applications are saving audit logs into a single database, set this property to your application name, so you can distinguish the logs of different applications. If you don't set, it will set from the `IApplicationInfoAccessor.ApplicationName` value, which is the entry assembly name by default.
* `IgnoredTypes`: A list of `Type`s to be ignored for audit logging. If this is an entity type, changes for this type of entities will not be saved. This list is also used while serializing the action parameters.

4
docs/en/suite/create-solution.md

@ -23,8 +23,8 @@
## Create a new solution
From ABP Suite v8.3, **create a new solution** option has been removed. Instead, it's suggessted to use [ABP Studio](../studio/index.md) or [ABP CLI](../cli/index.md) to create a new solution. After, creating an ABP Solution, then you can generate CRUD pages via ABP Suite as always.
From ABP Suite v8.3, **create a new solution** option has been removed. Instead, it's suggested to use [ABP Studio](../studio/index.md) or [ABP CLI](../cli/index.md) to create a new solution. After creating an ABP solution, you can generate CRUD pages via ABP Suite as usual.
> **Note:** ABP Suite does not generate React UI pages. If you create a modern React solution, use Suite where applicable for backend and application-layer generation, and develop the React UI in the source-owned [React UI](../framework/ui/react/index.md) application. ABP license holders can use [ABP Studio AI Agent](https://abp.io/studio/ai-agent) with predefined AI credits to generate React pages more easily.
> **Note:** For modern React UI solutions, ABP Suite generates the backend, the application layer and the React CRUD UI. Develop any React UI that generation does not cover in the source-owned [React UI](../framework/ui/react/index.md) application. ABP license holders can also use the [ABP Studio AI Agent](https://abp.io/studio/ai-agent) with predefined AI credits for React pages.
> ABP Studio has a shortcut for running [ABP Suite](./index.md) to allow using it without starting it externally and using it on a browser, which means you can create, manage, deploy your applications in a single desktop application and also generate CRUD pages via Suite as a pre-integrated application to ABP Studio.

2
docs/en/suite/creating-many-to-many-relationship.md

@ -75,6 +75,6 @@ Click the **Navigations** tab. Then click the **Add navigation collection** butt
The below image is the final page created by ABP Suite. The **new book** dialog has a **Categories** tab which lists all categories of the book and allows add/remove categories.
> **Note:** ABP Suite does not generate React UI for this page. The generated UI applies to Suite-supported UI stacks such as MVC, Blazor and Angular. ABP license holders can use [ABP Studio AI Agent](https://abp.io/studio/ai-agent) with predefined AI credits to generate React pages more easily.
> **Note:** For modern React UI solutions, ABP Suite generates the navigation collection as an inline multi-select on the entity's create/edit dialog — add or remove connected records, pre-selected when editing an existing record, and available as a list filter — alongside the MVC, Blazor and Angular UI stacks.
![navigation-collection-books-page](../images/navigation-collection-books-page.8.1.png)

2
docs/en/suite/creating-master-detail-relationship.md

@ -39,7 +39,7 @@ You need to specify the **Entity type** as _Master_ (default). Then, provide the
Create a child entity, specify the **Entity type** as _Child_, and associate it with a master entity. In the figure above, you can see an example of, a child entity **OrderLine** with the associated master entity **Order**. When you specify the **Entity type** as _Child_, then the UI and tests will not be generated for the child entity and instead, all of the orchestration of the entity will be delegated to its master entity.
> **Note:** ABP Suite does not generate React UI for master-detail pages. The generated UI applies to Suite-supported UI stacks such as MVC, Blazor and Angular. ABP license holders can use [ABP Studio AI Agent](https://abp.io/studio/ai-agent) with predefined AI credits to generate React pages more easily.
> **Note:** For modern React UI solutions, ABP Suite generates the master-detail UI: once the master record exists, each child entity renders as a sub-grid on its own tab inside the master edit dialog, with its own add/edit/delete dialog. This is generated in addition to the MVC, Blazor and Angular UI stacks.
Application services will be generated for the child entity, so it's possible for you to consume its endpoints and create-update-list or delete the child entity specifically. Suite also respects your multi-tenancy selection and sets the child entity as a multi-tenant entity, if the master entity has multi-tenancy enabled.

2
docs/en/suite/customizing-the-generated-code.md

@ -58,7 +58,7 @@ You can see the example below, which demonstrates defining a new method in the `
For the UI side, ABP Suite provides convenient comment placeholders within pages for MVC, Blazor, and Angular UIs. These comment sections serve as hook points where you can add your custom code. By placing your custom logic with these hook points, you can enhance the UI to your needs without the fear of losing your changes during the next CRUD page generation.
> **Note:** ABP Suite does not generate React UI pages or React customization hook points. React UI is part of ABP's modern template system and is customized directly in the source-owned [React UI](../framework/ui/react/index.md) application. ABP license holders can use [ABP Studio AI Agent](https://abp.io/studio/ai-agent) with predefined AI credits to generate React pages and customize them more easily.
> **Note:** These comment-based hook points are available for the MVC, Blazor and Angular UIs. ABP Suite also generates React CRUD pages for modern React UI solutions, but the React pages do not provide the same in-page custom-code hook points yet, so re-generating an entity overwrites its React page. Keep customizations to the React UI in the source-owned [React UI](../framework/ui/react/index.md) application, outside the generated pages. ABP license holders can also use the [ABP Studio AI Agent](https://abp.io/studio/ai-agent) with predefined AI credits to evolve the React UI.
### Customizations on MVC UI

7
docs/en/suite/editing-templates.md

@ -11,12 +11,12 @@ ABP Suite uses templates to generate the code files. You can see the template fi
![Suite template list](../images/suite-templates-8.1.png)
The are 2 template filters:
There are 2 template filters:
1. **UI**: You can switch between `Angular`, `MVC` and `Blazor` templates.
1. **UI**: You can switch between `Angular`, `MVC`, `Blazor` and `React` templates.
2. **Database provider:** You can switch between `EF Core` and `MongoDb` templates.
> **Note:** ABP Suite does not include React UI templates or generate React client-side code. React UI belongs to the modern template system and should be developed in the source-owned [React UI](../framework/ui/react/index.md) application. ABP license holders can use [ABP Studio AI Agent](https://abp.io/studio/ai-agent) with predefined AI credits to generate React pages more easily.
> **Note:** For modern React UI solutions, the React templates are listed here as well. Customizing one makes ABP Suite generate the React pages from your version instead of the built-in template, the same way as for the Angular, MVC and Blazor UI stacks.
These filters are automatically selected based on your ABP solution. The selected solution is shown on the top right of the page. In the current screenshot it is "Acme.BookStore".
@ -33,6 +33,7 @@ There's a naming convention for the template files.
* If the template name has `Frontend.Mvc` prefix, it's used for razor pages, menus, JavaScript, CSS files.
* If the template name has `Frontend.Blazor` prefix (no `.MudBlazor` segment), it's used for Blazorise-based razor components.
* If the template name has `Frontend.Blazor.MudBlazor` prefix, it's used for [MudBlazor](https://mudblazor.com)-based razor components.
* If the template name has `Frontend.React` prefix, it's used for the modern React UI code generation.
> The template list only shows the variant that matches your solution's [Blazor UI library](index.md#blazor-ui-library) (Blazorise or MudBlazor), so you never see both trees side-by-side and the "outdated" check only flags the active set.

2
docs/en/suite/generating-crud-page.md

@ -110,7 +110,7 @@ To create a new entity, make sure the *-New entity-* is selected in the **Entity
* **Create user interface:** Creates pages, modals, components, `JavaScript`, `CSS` files and adds the new page to the main menu. If you don't have a requirement to manage the entity via user interface, you can uncheck this option.
> **Note:** This option does not generate React UI pages. ABP Suite's UI generation targets Suite-supported UI stacks such as MVC, Blazor and Angular. For React-based solutions, build the UI in the source-owned [React UI](../framework/ui/react/index.md) application. ABP license holders can use [ABP Studio AI Agent](https://abp.io/studio/ai-agent) with predefined AI credits to generate React pages more easily.
> **Note:** For modern React UI solutions, this option also generates and registers React CRUD pages, alongside the MVC, Blazor and Angular UI stacks. React generation is template-based and does not use AI.
> **Blazor UI library:** For Blazor solutions, the generated UI matches the underlying Blazor component library. Solutions that reference `Volo.Abp.MudBlazorUI` produce pages built around `MudDataGrid`, `MudDialog`, `MudForm` and the rest of the [MudBlazor](https://mudblazor.com) controls; Blazorise-based solutions keep emitting the original `DataGrid` / `Modal` / `Validations` markup. ABP Suite picks the variant automatically by scanning the Blazor project `.csproj` and shows the resolved value in the solution info tooltip — no extra switch is required. See the [Blazor UI library](index.md#blazor-ui-library) section for details.

2
docs/en/suite/index.md

@ -21,7 +21,7 @@
ABP Suite is a complementary tool to the ABP Platform. ABP Suite allows you to build web pages in a matter of minutes.
> **Important:** ABP Suite does not generate React UI pages or client-side React code. Its CRUD UI generation is designed for the established Suite-supported UI stacks, such as MVC, Blazor and Angular. The new [React UI](../framework/ui/react/index.md) belongs to ABP's modern template system and is designed for an AI-first, AI-oriented development flow with a modern frontend stack such as React, TypeScript, Vite, TanStack Router, TanStack Query, shadcn/ui, Zod and React Hook Form. In React UI solutions, ABP Suite can still be useful for the backend and application layers where applicable, but the React UI side is expected to be developed in the source-owned React application. ABP license holders can use [ABP Studio AI Agent](https://abp.io/studio/ai-agent) with predefined AI credits to generate React pages and evolve the UI more easily.
> **Note:** ABP Suite also generates React CRUD pages for modern React UI solutions, in addition to the MVC, Blazor and Angular UI stacks. The generator is template-based and does not use AI. It covers the standard CRUD scenarios — navigation-property lookups, many-to-many navigation collections, master-detail child grids, file upload, enums, filtering, Excel export and bulk delete — and registers each page in the React app's route configuration and menu.
It's a .NET Core Global tool that can be installed from the command line. If you are using [ABP Studio](../studio/index.md), you don't even need to install it because it should already be installed, when you first installed the [ABP Studio](../studio/index.md).

5
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs

@ -1,5 +1,4 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Abstractions;
@ -7,6 +6,7 @@ using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Filters;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http;
using Volo.Abp.Threading;
using Volo.Abp.Uow;
@ -81,7 +81,8 @@ public class AbpUowActionFilter : IAsyncActionFilter, IAbpFilter, ITransientDepe
{
var abpUnitOfWorkDefaultOptions = context.GetRequiredService<IOptions<AbpUnitOfWorkDefaultOptions>>().Value;
options.IsTransactional = abpUnitOfWorkDefaultOptions.CalculateIsTransactional(
autoValue: !string.Equals(context.HttpContext.Request.Method, HttpMethod.Get.Method, StringComparison.OrdinalIgnoreCase)
autoValue: !(HttpMethodHelper.IsGet(context.HttpContext.Request.Method)
|| HttpMethodHelper.IsQuery(context.HttpContext.Request.Method))
);
}

5
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs

@ -1,5 +1,4 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Abstractions;
@ -7,6 +6,7 @@ using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Filters;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http;
using Volo.Abp.Threading;
using Volo.Abp.Uow;
@ -86,7 +86,8 @@ public class AbpUowPageFilter : IAsyncPageFilter, IAbpFilter, ITransientDependen
{
var abpUnitOfWorkDefaultOptions = context.GetRequiredService<IOptions<AbpUnitOfWorkDefaultOptions>>().Value;
options.IsTransactional = abpUnitOfWorkDefaultOptions.CalculateIsTransactional(
autoValue: !string.Equals(context.HttpContext.Request.Method, HttpMethod.Get.Method, StringComparison.OrdinalIgnoreCase)
autoValue: !(HttpMethodHelper.IsGet(context.HttpContext.Request.Method)
|| HttpMethodHelper.IsQuery(context.HttpContext.Request.Method))
);
}

6
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs

@ -7,6 +7,7 @@ using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Middleware;
using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http;
using Volo.Abp.Uow;
using Volo.Abp.Users;
@ -135,8 +136,9 @@ public class AbpAuditingMiddleware : AbpMiddlewareBase, ITransientDependency
}
if (!AuditingOptions.IsEnabledForGetRequests &&
(string.Equals(httpContext.Request.Method, HttpMethods.Get, StringComparison.OrdinalIgnoreCase) ||
string.Equals(httpContext.Request.Method, HttpMethods.Head, StringComparison.OrdinalIgnoreCase)))
(HttpMethodHelper.IsGet(httpContext.Request.Method) ||
HttpMethodHelper.IsHead(httpContext.Request.Method) ||
HttpMethodHelper.IsQuery(httpContext.Request.Method)))
{
return false;
}

8
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider.cs

@ -1,8 +1,8 @@
using System;
using System.Net.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http;
using Volo.Abp.Uow;
namespace Volo.Abp.AspNetCore.Uow;
@ -37,10 +37,8 @@ public class AspNetCoreUnitOfWorkTransactionBehaviourProvider : IUnitOfWorkTrans
}
}
return !string.Equals(
httpContext.Request.Method,
HttpMethod.Get.Method, StringComparison.OrdinalIgnoreCase
);
var method = httpContext.Request.Method;
return !(HttpMethodHelper.IsGet(method) || HttpMethodHelper.IsQuery(method));
}
}

1
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs

@ -62,6 +62,7 @@ public class AbpAuditingOptions
//TODO: Move this to asp.net core layer or convert it to a more dynamic strategy?
/// <summary>
/// Default: false.
/// When false, safe methods (GET, HEAD and QUERY) are excluded from audit logging.
/// </summary>
public bool IsEnabledForGetRequests { get; set; }

1
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs

@ -193,6 +193,7 @@ public class AuditingInterceptor : AbpInterceptor, ITransientDependency
if (!options.IsEnabledForGetRequests &&
(string.Equals(auditLogInfo.HttpMethod, "Get", StringComparison.OrdinalIgnoreCase) ||
string.Equals(auditLogInfo.HttpMethod, "Head", StringComparison.OrdinalIgnoreCase) ||
string.Equals(auditLogInfo.HttpMethod, "Query", StringComparison.OrdinalIgnoreCase) ||
invocation.Method.Name.StartsWith("Get", StringComparison.OrdinalIgnoreCase)))
{
return false;

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs

@ -9,5 +9,6 @@ public enum UiFramework
Blazor = 4,
BlazorServer = 5,
MauiBlazor = 6,
BlazorWebApp = 7
BlazorWebApp = 7,
React = 8
}

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFrameworkExtensions.cs

@ -12,6 +12,7 @@ public static class UiFrameworkExtensions
case UiFramework.Blazor: return "blazor";
case UiFramework.BlazorServer: return "blazor-server";
case UiFramework.BlazorWebApp: return "blazor-webapp";
case UiFramework.React: return "react";
case UiFramework.NotSpecified: return "NotSpecified";
default: return "NotSpecified";
}

9
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs

@ -59,6 +59,15 @@ public class TemplateProjectBuilder : IProjectBuilder, ITransientDependency
NormalizeArgs(args, templateInfo);
// Checked after NormalizeArgs so a NotSpecified UI resolved to React is caught too. React is only
// produced by ABP Studio's modern solution templates; the classic builders below have no React
// handling, so fail fast instead of emitting a solution with an unconfigured UI.
if (args.UiFramework == UiFramework.React)
{
throw new UserFriendlyException(
"The React UI is generated by ABP Studio's modern solution templates and is not supported by the classic template builder.");
}
await EventBus.PublishAsync(new ProjectCreationProgressEvent {
Message = "Downloading the solution template"
}, false);

62
framework/src/Volo.Abp.Http/Volo/Abp/Http/HttpMethodHelper.cs

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
@ -8,15 +8,25 @@ namespace Volo.Abp.Http;
public static class HttpMethodHelper
{
public const string DefaultHttpVerb = "POST";
public const string Get = "GET";
public const string Post = "POST";
public const string Put = "PUT";
public const string Delete = "DELETE";
public const string Patch = "PATCH";
public const string Head = "HEAD";
public const string Options = "OPTIONS";
public const string Trace = "TRACE";
public const string Query = "QUERY";
public const string DefaultHttpVerb = Post;
public static Dictionary<string, string[]> ConventionalPrefixes { get; set; } = new Dictionary<string, string[]>
{
{"GET", new[] {"GetList", "GetAll", "Get"}},
{"PUT", new[] {"Put", "Update"}},
{"DELETE", new[] {"Delete", "Remove"}},
{"POST", new[] {"Create", "Add", "Insert", "Post"}},
{"PATCH", new[] {"Patch"}}
{Get, new[] {"GetList", "GetAll", "Get"}},
{Put, new[] {"Put", "Update"}},
{Delete, new[] {"Delete", "Remove"}},
{Post, new[] {"Create", "Add", "Insert", "Post"}},
{Patch, new[] {"Patch"}}
};
public static string GetConventionalVerbForMethodName(string methodName)
@ -50,24 +60,44 @@ public static class HttpMethodHelper
{
switch (httpMethod?.ToUpperInvariant())
{
case "GET":
case Get:
return HttpMethod.Get;
case "POST":
case Post:
return HttpMethod.Post;
case "PUT":
case Put:
return HttpMethod.Put;
case "DELETE":
case Delete:
return HttpMethod.Delete;
case "OPTIONS":
case Options:
return HttpMethod.Options;
case "TRACE":
case Trace:
return HttpMethod.Trace;
case "HEAD":
case Head:
return HttpMethod.Head;
case "PATCH":
return new HttpMethod("PATCH");
case Patch:
return new HttpMethod(Patch);
case Query:
return new HttpMethod(Query);
default:
throw new AbpException("Unknown HTTP METHOD: " + httpMethod);
}
}
public static bool IsGet(string? httpMethod) => string.Equals(httpMethod, Get, StringComparison.OrdinalIgnoreCase);
public static bool IsPost(string? httpMethod) => string.Equals(httpMethod, Post, StringComparison.OrdinalIgnoreCase);
public static bool IsPut(string? httpMethod) => string.Equals(httpMethod, Put, StringComparison.OrdinalIgnoreCase);
public static bool IsDelete(string? httpMethod) => string.Equals(httpMethod, Delete, StringComparison.OrdinalIgnoreCase);
public static bool IsPatch(string? httpMethod) => string.Equals(httpMethod, Patch, StringComparison.OrdinalIgnoreCase);
public static bool IsHead(string? httpMethod) => string.Equals(httpMethod, Head, StringComparison.OrdinalIgnoreCase);
public static bool IsOptions(string? httpMethod) => string.Equals(httpMethod, Options, StringComparison.OrdinalIgnoreCase);
public static bool IsTrace(string? httpMethod) => string.Equals(httpMethod, Trace, StringComparison.OrdinalIgnoreCase);
public static bool IsQuery(string? httpMethod) => string.Equals(httpMethod, Query, StringComparison.OrdinalIgnoreCase);
}

14
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs

@ -58,6 +58,20 @@ public class AuditTestController_Tests : AspNetCoreMvcTestBase
await _auditingStore.Received().DidNotReceive().SaveAsync(Arg.Any<AuditLogInfo>());
}
[Fact]
public async Task Should_Disable_AuditLog_For_Query_Requests()
{
_options.IsEnabledForGetRequests = false;
using (var requestMessage = new HttpRequestMessage(new HttpMethod("QUERY"), "api/audit-test/audit-success"))
{
var response = await Client.SendAsync(requestMessage);
response.StatusCode.ShouldBe(System.Net.HttpStatusCode.OK);
}
await _auditingStore.Received().DidNotReceive().SaveAsync(Arg.Any<AuditLogInfo>());
}
[Fact]
public async Task Should_Trigger_Middleware_And_AuditLog_Success_For_GetRequests()
{

11
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkMiddleware_Tests.cs

@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System.Net.Http;
using System.Threading.Tasks;
using Shouldly;
using Xunit;
@ -18,4 +19,12 @@ public class UnitOfWorkMiddleware_Tests : AspNetCoreMvcTestBase
var result = await Client.PostAsync("/api/unitofwork-test/ActionRequiresUowPost", null);
result.IsSuccessStatusCode.ShouldBeTrue();
}
[Fact]
public async Task Query_Actions_Should_Not_Be_Transactional()
{
using var requestMessage = new HttpRequestMessage(new HttpMethod("QUERY"), "/api/unitofwork-test/ActionRequiresUowQuery");
var result = await Client.SendAsync(requestMessage);
result.IsSuccessStatusCode.ShouldBeTrue();
}
}

11
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Tests.cs

@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System.Net.Http;
using System.Threading.Tasks;
using Shouldly;
using Xunit;
@ -18,4 +19,12 @@ public class UnitOfWorkPageFilter_Tests : AspNetCoreMvcTestBase
var result = await Client.PostAsync("/Uow/UnitOfWorkTestPage?handler=RequiresUow", null);
result.IsSuccessStatusCode.ShouldBeTrue();
}
[Fact]
public async Task Query_Actions_Should_Not_Be_Transactional()
{
using var requestMessage = new HttpRequestMessage(new HttpMethod("QUERY"), "/Uow/UnitOfWorkTestPage?handler=RequiresUow");
var result = await Client.SendAsync(requestMessage);
result.IsSuccessStatusCode.ShouldBeTrue();
}
}

10
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestController.cs

@ -34,6 +34,16 @@ public class UnitOfWorkTestController : AbpController
return Content("OK");
}
[AcceptVerbs("QUERY")]
[Route("ActionRequiresUowQuery")]
public ActionResult ActionRequiresUowQuery()
{
CurrentUnitOfWork.ShouldNotBeNull();
CurrentUnitOfWork.Options.IsTransactional.ShouldBeFalse();
return Content("OK");
}
[HttpGet]
[Route("HandledException")]
[UnitOfWork(isTransactional: true)]

8
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml.cs

@ -31,6 +31,14 @@ public class UnitOfWorkTestPage : AbpPageModel
return Content("OK");
}
public IActionResult OnQueryRequiresUow()
{
CurrentUnitOfWork.ShouldNotBeNull();
CurrentUnitOfWork.Options.IsTransactional.ShouldBeFalse();
return Content("OK");
}
[UnitOfWork(isTransactional: true)]
public ObjectResult OnGetHandledException()
{

32
framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider_Tests.cs

@ -0,0 +1,32 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Shouldly;
using Xunit;
namespace Volo.Abp.AspNetCore.Uow;
public class AspNetCoreUnitOfWorkTransactionBehaviourProvider_Tests
{
private static AspNetCoreUnitOfWorkTransactionBehaviourProvider CreateProvider(string method)
{
var httpContext = new DefaultHttpContext();
httpContext.Request.Method = method;
return new AspNetCoreUnitOfWorkTransactionBehaviourProvider(
new HttpContextAccessor { HttpContext = httpContext },
Microsoft.Extensions.Options.Options.Create(new AspNetCoreUnitOfWorkTransactionBehaviourProviderOptions()));
}
[Theory]
[InlineData("GET", false)]
[InlineData("QUERY", false)]
[InlineData("query", false)]
[InlineData("HEAD", true)]
[InlineData("POST", true)]
[InlineData("PUT", true)]
[InlineData("DELETE", true)]
public void IsTransactional_Should_Treat_Get_And_Query_As_Non_Transactional(string method, bool expected)
{
CreateProvider(method).IsTransactional.ShouldBe(expected);
}
}

64
framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/AuditingInterceptor_HttpMethod_Tests.cs

@ -0,0 +1,64 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using NSubstitute;
using Xunit;
namespace Volo.Abp.Auditing;
public class AuditingInterceptor_HttpMethod_Tests : AbpAuditingTestBase
{
protected IAuditingStore AuditingStore;
private string? _httpMethod;
protected override void AfterAddApplication(IServiceCollection services)
{
AuditingStore = Substitute.For<IAuditingStore>();
services.Replace(ServiceDescriptor.Singleton(AuditingStore));
services.Configure<AbpAuditingOptions>(options =>
{
options.IsEnabledForGetRequests = false;
options.Contributors.Add(new TestHttpMethodAuditContributor(() => _httpMethod));
});
}
[Fact]
public async Task Should_Not_Write_AuditLog_For_Query_Http_Method_Without_Explicit_Scope()
{
_httpMethod = "QUERY";
var auditedObject = GetRequiredService<Auditing_Tests.MyAuditedObject1>();
await auditedObject.DoItAsync(new Auditing_Tests.InputObject { Value1 = "x", Value2 = 1 });
await AuditingStore.DidNotReceive().SaveAsync(Arg.Any<AuditLogInfo>());
}
[Fact]
public async Task Should_Write_AuditLog_For_Post_Http_Method_Without_Explicit_Scope()
{
_httpMethod = "POST";
var auditedObject = GetRequiredService<Auditing_Tests.MyAuditedObject1>();
await auditedObject.DoItAsync(new Auditing_Tests.InputObject { Value1 = "x", Value2 = 1 });
await AuditingStore.Received().SaveAsync(Arg.Any<AuditLogInfo>());
}
public class TestHttpMethodAuditContributor : AuditLogContributor
{
private readonly Func<string?> _httpMethodFactory;
public TestHttpMethodAuditContributor(Func<string?> httpMethodFactory)
{
_httpMethodFactory = httpMethodFactory;
}
public override void PreContribute(AuditLogContributionContext context)
{
context.AuditInfo.HttpMethod = _httpMethodFactory();
}
}
}

2
framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/IRegularTestController.cs

@ -43,6 +43,8 @@ public interface IRegularTestController
Task<Car> PostObjectWithQueryAsync(Car bodyValue);
Task<Car> QueryObjectWithBodyAsync(Car bodyValue);
Task<Car> GetObjectWithUrlAsync(Car bodyValue);
Task<Car> GetObjectandIdAsync(int id, Car bodyValue);

7
framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs

@ -150,6 +150,13 @@ public class RegularTestController : AbpController, IRegularTestController
return Task.FromResult(bodyValue);
}
[AcceptVerbs("QUERY")]
[Route("query-object-with-body")]
public Task<Car> QueryObjectWithBodyAsync([FromBody] Car bodyValue)
{
return Task.FromResult(bodyValue);
}
[HttpGet]
[Route("post-object-with-url/bodyValue")]
public Task<Car> GetObjectWithUrlAsync(Car bodyValue)

8
framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs

@ -97,6 +97,14 @@ public class RegularTestControllerClientProxy_Tests : AbpHttpClientTestBase
result.Model.ShouldBe("Ford");
}
[Fact]
public async Task QueryObjectWithBodyAsync()
{
var result = await _controller.QueryObjectWithBodyAsync(new Car { Year = 1976, Model = "Ford", FirstReleaseDate = new DateTime(1976, 02, 22, 15, 0, 6, 22) });
result.Year.ShouldBe(1976);
result.Model.ShouldBe("Ford");
}
[Fact]
public async Task PostObjectWithQueryAsync_With_Different_Culture()
{

105
framework/test/Volo.Abp.Http.Tests/Volo/Abp/Http/HttpMethodHelper_Tests.cs

@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using Shouldly;
using Xunit;
namespace Volo.Abp.Http;
public class HttpMethodHelper_Tests
{
private static readonly Dictionary<string, Func<string?, bool>> Predicates = new()
{
[HttpMethodHelper.Get] = HttpMethodHelper.IsGet,
[HttpMethodHelper.Post] = HttpMethodHelper.IsPost,
[HttpMethodHelper.Put] = HttpMethodHelper.IsPut,
[HttpMethodHelper.Delete] = HttpMethodHelper.IsDelete,
[HttpMethodHelper.Patch] = HttpMethodHelper.IsPatch,
[HttpMethodHelper.Head] = HttpMethodHelper.IsHead,
[HttpMethodHelper.Options] = HttpMethodHelper.IsOptions,
[HttpMethodHelper.Trace] = HttpMethodHelper.IsTrace,
[HttpMethodHelper.Query] = HttpMethodHelper.IsQuery
};
[Theory]
[InlineData(HttpMethodHelper.Get)]
[InlineData(HttpMethodHelper.Post)]
[InlineData(HttpMethodHelper.Put)]
[InlineData(HttpMethodHelper.Delete)]
[InlineData(HttpMethodHelper.Patch)]
[InlineData(HttpMethodHelper.Head)]
[InlineData(HttpMethodHelper.Options)]
[InlineData(HttpMethodHelper.Trace)]
[InlineData(HttpMethodHelper.Query)]
public void Is_Predicates_Should_Match_Only_Their_Own_Verb_Ignoring_Case(string verb)
{
foreach (var (name, predicate) in Predicates)
{
var shouldMatch = name == verb;
predicate(verb).ShouldBe(shouldMatch);
predicate(verb.ToLowerInvariant()).ShouldBe(shouldMatch);
}
}
[Fact]
public void Is_Predicates_Should_Return_False_For_Null()
{
foreach (var predicate in Predicates.Values)
{
predicate(null).ShouldBeFalse();
}
}
[Theory]
[InlineData("QUERY", true)]
[InlineData("query", true)]
[InlineData("Query", true)]
[InlineData("GET", false)]
[InlineData("POST", false)]
[InlineData("", false)]
[InlineData(null, false)]
public void IsQuery_Should_Match_Query_Method_Ignoring_Case(string? httpMethod, bool expected)
{
HttpMethodHelper.IsQuery(httpMethod).ShouldBe(expected);
}
[Fact]
public void ConvertToHttpMethod_Should_Support_Query()
{
HttpMethodHelper.ConvertToHttpMethod("QUERY").Method.ShouldBe("QUERY");
HttpMethodHelper.ConvertToHttpMethod("query").Method.ShouldBe("QUERY");
}
[Theory]
[InlineData("GET")]
[InlineData("POST")]
[InlineData("PUT")]
[InlineData("DELETE")]
[InlineData("PATCH")]
[InlineData("QUERY")]
public void ConvertToHttpMethod_Should_Not_Throw_For_Known_Methods(string httpMethod)
{
Should.NotThrow(() => HttpMethodHelper.ConvertToHttpMethod(httpMethod));
}
[Fact]
public void ConvertToHttpMethod_Should_Throw_For_Unknown_Method()
{
Should.Throw<AbpException>(() => HttpMethodHelper.ConvertToHttpMethod("UNKNOWN"));
}
[Theory]
[InlineData("GetFooAsync", "GET")]
[InlineData("GetListAsync", "GET")]
[InlineData("CreateFooAsync", "POST")]
[InlineData("UpdateFooAsync", "PUT")]
[InlineData("DeleteFooAsync", "DELETE")]
[InlineData("PatchFooAsync", "PATCH")]
[InlineData("DoSomethingAsync", "POST")]
// QUERY is intentionally NOT a naming convention: an action must opt in explicitly
// with [AcceptVerbs("QUERY")]. A method named Query* still maps to the default verb.
[InlineData("QueryFooAsync", "POST")]
public void GetConventionalVerbForMethodName_Should_Not_Map_Query_By_Name(string methodName, string expectedVerb)
{
HttpMethodHelper.GetConventionalVerbForMethodName(methodName).ShouldBe(expectedVerb);
}
}

1
modules/docs/src/Volo.Docs.Admin.HttpApi.Client/Volo.Docs.Admin.HttpApi.Client.csproj

@ -13,6 +13,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Docs.Admin.Application.Contracts\Volo.Docs.Admin.Application.Contracts.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Http.Client\Volo.Abp.Http.Client.csproj" />
<ProjectReference Include="..\Volo.Docs.Common.HttpApi.Client\Volo.Docs.Common.HttpApi.Client.csproj" />
</ItemGroup>

1
modules/docs/src/Volo.Docs.Admin.HttpApi.Client/Volo/Docs/Admin/DocsAdminHttpApiClientModule.cs

@ -6,6 +6,7 @@ using Volo.Abp.VirtualFileSystem;
namespace Volo.Docs.Admin
{
[DependsOn(
typeof(DocsCommonHttpApiClientModule),
typeof(DocsAdminApplicationContractsModule),
typeof(AbpHttpClientModule))]
public class DocsAdminHttpApiClientModule : AbpModule

1
modules/docs/src/Volo.Docs.HttpApi.Client/Volo.Docs.HttpApi.Client.csproj

@ -13,6 +13,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Docs.Application.Contracts\Volo.Docs.Application.Contracts.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Http.Client\Volo.Abp.Http.Client.csproj" />
<ProjectReference Include="..\Volo.Docs.Common.HttpApi.Client\Volo.Docs.Common.HttpApi.Client.csproj" />
</ItemGroup>
</Project>

1
modules/docs/src/Volo.Docs.HttpApi.Client/Volo/Docs/DocsHttpApiClientModule.cs

@ -6,6 +6,7 @@ using Volo.Abp.VirtualFileSystem;
namespace Volo.Docs
{
[DependsOn(
typeof(DocsCommonHttpApiClientModule),
typeof(DocsApplicationContractsModule),
typeof(AbpHttpClientModule)
)]

6
npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.html

@ -162,11 +162,7 @@
@if (prop().displayTextResolver) {
{{ prop().displayTextResolver(data()) | abpLocalization }}
} @else {
@if (prop().isExtra) {
{{ '::' + prop().displayName | abpLocalization }}
} @else {
{{ prop().displayName | abpLocalization }}
}
{{ prop().displayName | abpLocalization }}
}
{{ asterisk() }}
@if (prop().tooltip) {

2
npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html

@ -136,7 +136,7 @@
*abpVisible="prop.columnVisible(getInjected)"
[width]="columnWidths()[i] || 200"
[canAutoResize]="!columnWidths()[i]"
[name]="(prop.isExtra ? '::' + prop.displayName : prop.displayName) | abpLocalization"
[name]="prop.displayName | abpLocalization"
[prop]="prop.name"
[sortable]="prop.sortable"
>

12
npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts

@ -13,11 +13,17 @@ export function createLocalizer(localization: ApplicationLocalizationConfigurati
return (resourceName: string, key: string, defaultValue: string | null) => {
if (resourceName === '_') return key;
const resource = localization?.values?.[resourceName];
const resource = localization?.resources?.[resourceName];
if (!resource) return defaultValue;
if (!resource) {
const fallbackResource = localization?.values?.[resourceName];
return resource[key] || defaultValue;
if (!fallbackResource) return defaultValue;
return fallbackResource[key] || defaultValue;
}
return resource.texts?.[key] || defaultValue;
};
}

Loading…
Cancel
Save