"MasteringTheABPFrameworkExplanation":"Written by the creator of the ABP Framework, this book will help you gain a complete understanding of the framework and modern web application development techniques."
"BackOfficeApplicationExplanation":"The actual web application of your system, with multiple UI framework options. You can create any kind of business application.",
"LandingWebsite":"Landing Website",
"LandingWebsiteExplanation":"A generic landing/public website that can be used for several purposes, like introducing your company, selling your products, etc."
"LandingWebsiteExplanation":"A generic landing/public website that can be used for several purposes, like introducing your company, selling your products, etc.",
"ThemingExplanationShort":"Use and customize the bootstrap-based standard UI theme or create your own.",
"BootstrapTagHelpersDynamicForms":"Bootstrap Tag Helpers & Dynamic Forms",
"BootstrapTagHelpersDynamicFormsExplanation":"Instead of manually writing the repeating details of bootstrap components, Use ABP's tag helpers to simplify them and take advantage of the IntelliSense. Quickly build UI forms based on a C# model using the dynamic form tag helper.",
"BootstrapTagHelpersDynamicFormsExplanation":"Instead of manually writing the repeating details of bootstrap components, use ABP's tag helpers to simplify them and take advantage of the IntelliSense. Quickly build UI forms based on a C# model using the dynamic form tag helper.",
"HTTPAPIsDynamicProxiesExplanation":"Automatically expose application services as REST style HTTP APIs, and consume them with dynamic JavaScript and C# proxies.",
"CompleteArchitectureInfo":"Modern architecture to create maintainable software solutions.",
"DomainDrivenDesignBasedLayeringModelExplanation":"Helps implement a DDD based layered architecture and builds a maintainable code base.",
"DomainDrivenDesignBasedLayeringModelExplanation":"Helps implement a DDD based layered architecture and build a maintainable code base.",
"DomainDrivenDesignBasedLayeringModelExplanationCont":"Provides startup templates, abstractions, base classes, services, documentation and guides to help you develop your application based on DDD patterns & principles.",
"MicroserviceCompatibleModelExplanation":"The core framework & pre-built modules are designed with microservice architecture in mind.",
"MicroserviceCompatibleModelExplanationCont":"Provides infrastructure, integrations, samples and documentation to implement microservice solutions easier, while it doesn\u2019t bring additional complexity if you want a monolithic application.",
@ -82,7 +82,7 @@
"CLI_CommandLineInterface":"CLI (Command Line Interface)",
"CLI_CommandLineInterfaceExplanation":"Includes a CLI to help you automate the creation of new projects and the addition of new modules.",
"StartupTemplates":"Startup Templates",
"StartupTemplatesExplanation":"Various startup templates provide a fully configured solution to jump start your development.",
"StartupTemplatesExplanation":"ABP’s application startup template provides a fully configured solution to jump start your development.",
"BasedOnFamiliarTools":"Based on Familiar Tools",
"BasedOnFamiliarToolsExplanation":"Built on and integrated with popular tools you already know. Low learning curve, easy adaptation, comfortable development.",
"DependencyInjectionByConventions":"Dependency Injection by Conventions",
"ABPCLIExplanation":"ABP CLI (Command Line Interface) is a command line tool to perform some common operations for ABP based solutions.",
"ABPCLIExplanation":"ABP CLI (Command Line Interface) is a command line tool to automate some common operations for ABP based solutions.",
"ModularityExplanation":"ABP provides a complete infrastructure to build your own application modules that may have entities, services, database integration, APIs, UI components and so on..",//TODO:strong"your own application modules",-
"MultiTenancyExplanation":"ABP framework doesn't only support developing multi-tenant applications, but also makes your code mostly unaware of the multi-tenancy.",
"MultiTenancyExplanation2":"Can automatically determine the current tenant, isolate data of different tenants from each other.",
@ -305,7 +305,6 @@
"FrameworkNewsletterConfirmationMessage":"I agree to the <a class=\"text-white fw-6 text-decoration-underline opacity-50\" href=\"https://commercial.abp.io/TermsConditions\">Terms & Conditions</a> and <a class=\"text-white fw-6 text-decoration-underline opacity-50\" href=\"https://commercial.abp.io/Privacy\">Privacy Policy</a>.",
"GetYourFreeEBook":"Get Your <span class=\"gradient-framework d-block\">Free DDD E-book </span>",
"EverythingYouNeedToKnow":"Everything you need to know.",
"MasteringTheABPFrameworkExplanation":"Written by the creator of ABP Framework, this book will help you gain a complete understanding of the framework and modern web application development techniques.",
"PreOrderNow":"Pre-Order Now",
"UITheming":"UI Theming",
"UIThemingExplanation":"Create reusable UI themes and layouts or use one of the pre-built UI themes.",
@ -61,7 +61,7 @@ public class Book : AggregateRoot<Guid>
* `Book` entity has a `MaxNameLength` that defines the maximum length of the `Name` property.
* `Book` constructor and `ChangeName` method to ensure that the `Name` is always a valid value. Notice that `Name`'s setter is not `public`.
> ABP does not force you to design your entities like that. It just can have public get/set for all properties. It's your decision to full implement DDD practices.
> ABP does not force you to design your entities like that. It just can have public get/set for all properties. It's your decision to fully implement DDD practices.
### IBookAppService Interface
@ -124,13 +124,13 @@ public class BookAppService : ApplicationService, IBookAppService
## Data Transfer Objects
Application services gets and returns DTOs instead of entities. ABP does not force this rule. However, exposing entities to presentation layer (or to remote clients) have significant problems and not suggested.
Application services get and return DTOs instead of entities. ABP does not force this rule. However, exposing entities to the presentation layer (or to remote clients) has significant problems and is not suggested.
See the [DTO documentation](Data-Transfer-Objects.md) for more.
## Object to Object Mapping
The `CreateAsync` method above manually creates a `Book` entity from given `CreateBookDto` object. Because the `Book` entity enforces it (we designed it like that).
The `CreateAsync` method above manually creates a `Book` entity from given `CreateBookDto` object, because the `Book` entity enforces it (we designed it like that).
However, in many cases, it's very practical to use **auto object mapping** to set properties of an object from a similar object. ABP provides an [object to object mapping](Object-To-Object-Mapping.md) infrastructure to make this even easier.
@ -239,7 +239,7 @@ public interface IBookAppService :
`ICrudAppService` has generic arguments to get the primary key type of the entity and the DTO types for the CRUD operations (it does not get the entity type since the entity type is not exposed to the clients use this interface).
> Creating interface for an application service is a good practice, but not required by the ABP Framework. You can skip the interface part.
> Creating an interface for an application service is good practice, but not required by the ABP Framework. You can skip the interface part.
`ICrudAppService` declares the following methods:
@ -359,7 +359,7 @@ public class DistrictAppService
}
````
This implementation requires you to create a class represents your composite key:
This implementation requires you to create a class that represents your composite key:
In this article, we will show how to show/hide ABP related endpoints on Swagger UI by enabling/disabling them on the Setting Management page.
I wanted to write an article about this topic because there was a [Github issue](https://github.com/abpframework/abp/issues/3758) and when I saw it, it seemed that so many people needed to hide the ABP related endpoints since they didn't need to see them as they were developing an application, they only need to see their own endpoints most of the time.
In the issue, there are helpful comments about hiding the ABP related endpoints such as creating a **Document Filter** or removing **Application Parts** from the application etc.
I thought it would be better to enable/disable showing endpoints on runtime by simply selecting a checkbox on the Setting Management page and in this article I wanted to show you how, so let's dive in.
## Source Code
You can find the source code of the application at https://github.com/EngincanV/ABP-Hide-Swagger-Endpoint-Demo.
## Creating the Solution
In this article, we will create a new startup template with EF Core as a database provider and MVC for the UI framework.
> But if you already have a project with MVC UI, you don't need to create a new startup template, you can directly implement the following steps to your existing project.
We can create a new startup template by using the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI):
```bash
abp new <your-project-name> -t app -csf
```
Our project boilerplate will be ready after the download is finished. Open the solution and run the `*.DbMigrator` project to seed the initial data. Then, we can run the `*.Web` project to see our application working.
> Default credentials -> Username: admin and Password: 1q2w3E*
## Starting the Development
After we've run the application and signed in, we can navigate to **/swagger** to see our application's endpoints.

In our scenario, we will hide endpoints that start with "/api/abp". So let's start to do this.
> In this sample project, we only hide our endpoints that start with the "/api/abp" prefix by definining it in our [CustomSwaggerFilter](https://github.com/EngincanV/ABP-Hide-Swagger-Endpoint-Demo/blob/main/src/SwaggerSettingsDemo.Web/Filters/CustomSwaggerFilter.cs#L29). If you want to hide some other endpoints, you can update the class.
* Firstly, create a class named `SwaggerSettingConsts` (under `*.Domain.Shared` project):
```csharp
namespace SwaggerSettingsDemo;
public class SwaggerSettingConsts
{
public const string HideEndpoint = "SwaggerHideEndpoint";
}
```
We've created a class with a constant variable to avoid using the magic strings. This variable will be our setting name.
ABP provides us a [Settings System](https://docs.abp.io/en/abp/latest/Setting) to easily define settings for our applications. We only need to create a class that derives from the `SettingDefinitionProvider` class, but we don't even need to do this because the ABP startup templates come with a pre-defined setting provider class.
* So open the setting definition provider class (`SwaggerSettingsDemoSettingDefinitionProvider` in our case, it's under the /Settings folder of your domain layer) and update the class:
```csharp
using SwaggerSettingsDemo.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Settings;
namespace SwaggerSettingsDemo.Settings;
public class SwaggerSettingsDemoSettingDefinitionProvider : SettingDefinitionProvider
{
public override void Define(ISettingDefinitionContext context)
We've injected two interfaces for the application service implementation: `ISettingProvider` and `ISettingManager`
> **ISettingProvider**: Used for getting the value of a setting or getting the values of all settings. It's recommended to use it to read the setting values because it implements caching.
> **ISettingManager**: Used for getting and setting the values of the settings.
After implementing our application service, now we can add a new group to our "Setting Management UI".
* Open the `*.Web` project and create a file named `SwaggerHideEndpointsViewComponent`(/Components/SwaggerHideEndpoints/SwaggerHideEndpointsViewComponent.cs):
bool.TryParse(swaggerHideEndpointSetting, out var hideEndpoints) && hideEndpoints
});
}
}
```
Here we've created a simple view component that gets the current value of our setting by using the `ISwaggerSettingAppService.GetSettingByNameAsync` method and passing it to our page model.
As you can see we've passed a modal to our page named `SwaggerHideEndpointViewModel`, but we haven't created it yet, so let's create it.
* Create a model named `SwaggerHideEndpointViewModel`(/Models/SwaggerHideEndpointViewModel.cs) :
```csharp
public class SwaggerHideEndpointViewModel
{
public bool HideEndpoints { get; set; }
}
```
* After creating the model, now we can create the **Default.cshtml** (/Components/SwaggerHideEndpoints/Default.cshtml) file (which will render in our Setting Management page as a new group):
After we've selected the select box which enables/disables to showing endpoints on Swagger UI, it should update the setting value by our choice (enable or disable).
Here, when the user selects the checkbox, it will submit the form and update the setting value by our choice.
Until now, we've defined a view component that we want to render on the Setting Management page, but we didn't add it to the UI yet. To do that, we need to add a settings group to the UI, so we need to create a class and that class should be inherited from the `ISettingPageContributor` interface and implement its' `ConfigureAsync` method.
* Create a class named `SwaggerSettingPageContributor` (/Settings/SwaggerSettingPageContributor.cs) in the `*.Web` layer:
```csharp
using System.Threading.Tasks;
using SwaggerSettingsDemo.Web.Components.SwaggerHideEndpoints;
using Volo.Abp.SettingManagement.Web.Pages.SettingManagement;
namespace SwaggerSettingsDemo.Web.Settings;
public class SwaggerSettingPageContributor : ISettingPageContributor
{
public Task ConfigureAsync(SettingPageCreationContext context)
{
context.Groups.Add(
new SettingPageGroup(
"MySwaggerSettingWrapper",
"Swagger",
typeof(SwaggerHideEndpointsViewComponent)
)
);
return Task.CompletedTask;
}
public Task<bool> CheckPermissionsAsync(SettingPageCreationContext context)
{
//we can check a permission in here, but for now just assume the permission is granted.
return Task.FromResult(true);
}
}
```
To see our new setting group on the Setting Management page, we need to do one more thing.
* So, open the `*WebModule.cs` class and configure the `SettingManagementPageOptions`:
```csharp
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = context.Services.GetConfiguration();
After all these steps, if we run our application and navigate to **/SettingManagement** page we need to see our setting group on this page.

To hide/show ABP related endpoints on Swagger UI, we can create a [`DocumentFilter`](https://github.com/domaindrivendev/Swashbuckle.AspNetCore#document-filters). By creating a document filter, we can have full control over the endpoints that need to be shown.
* Create a document filter class named `CustomSwaggerFilter`(/Filters/CustomSwaggerFilter.cs) in the `.Web` layer:
```csharp
using System.Linq;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using Volo.Abp.Threading;
namespace SwaggerSettingsDemo.Web.Filters;
public class CustomSwaggerFilter : IDocumentFilter
We've created a simple class that implements `IDocumentFilter.Apply` method. And in that method, we simply need to get our setting value to see whether should we enable hiding ABP related endpoints or not. To do this, we've used the `ISwaggerSettingAppService.GetSettingByNameAsync` method to get the setting value, but as you can see we've wrapped it with the `AsyncHelper.RunSync` method because `IDocumentFilter.Apply` is not an async method so we need to run this method synchronously.
After getting the setting value, we need to ensure that it's both a valid and true setting value, otherwise we don't need to filter the endpoints and show all of them.
If the setting value is true, we can simply remove the paths that start with "/api/abp" prefix.
> ABP provides us a class named AsyncHelper and this class provides some helper methods to work with async methods. E.g. RunSync method in here runs the async method synchronously.
* Finally, we can add this document filter as a swagger document filter. To do this we need to open the `ConfigureSwaggerServices` method in the `*WebModule.cs` class and update the content as below: