Version

Add Module to Existing Microservices

This documentation introduces guidance for adding a module to a microservice for your microservice template project. Eventually, every module has its own documentation and implementation steps. However, some steps can be different for the microservice template. This guide will demonstrate the steps to add a module to an existing microservice.

Adding a module

After adding a new service to your microservice template by following the add new microservice guide, you can add any module to this service in your microservice solution by using the ABP CLI. Use the following command to add the preferred module under the newly added microservice directory:

abp add-module CmsKit

To complete the CmsKit module steps, please have a look here.

After completing the module documentation steps you can build your solution and continue with this documentation.

dotnet build

Using the static proxy

ABP Framework supports dynamic and static proxies. Both have advantages and disadvantages. By default, the static proxy is used in the microservice template to remove the coupling between services. The static proxy should be configured manually in the HttpApiClientModule of the microservice you have installed your module on as below:

public class ProductServiceHttpApiClientModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        //Make sure this is `AddStaticHttpClientProxies` 
        context.Services.AddHttpClientProxies(typeof(ProductServiceHttpApiClientModule).Assembly,
            ProductServiceRemoteServiceConsts.RemoteServiceName);

        Configure<AbpVirtualFileSystemOptions>(options =>
        {
            options.FileSets.AddEmbedded<ProductServiceHttpApiClientModule>();
        });
    }
}

If the proxy is configured as AddStaticHttpClientProxies, you can start creating the static proxies in ProductService.HttpApi.Client by using the following command line:

abp generate-proxy --type csharp --module cms-kit --url https://localhost:44335

Note: This port is used by Public-Web. You can check your port from launchSetting.json. The Public Web calls the Public Web Gateway so it has called the related services and has generated proxy files. For more

If you have generated a new microservice with the ABP CLI by following the add new microservice guide, it should already be configured to use the static proxy.

Configure Gateways

The microservice template project has two gateway projects.

  • WebGateway
  • PublicWebGateway

The first one is for the admin side and the other one is for the public side. If you would like to use your module on both sides, you should configure ocelot.json in both projects. There is one example below and you need to configure it according to your requirements.

{
    "ServiceKey": "CmsKit",
    "DownstreamPathTemplate": "/api/cms-kit-public/{everything}",
    "DownstreamScheme": "https",
    "DownstreamHostAndPorts": [
        {
            "Host": "localhost",
            "Port": 44361 **This port used in ProductService**
        }
    ],
    "UpstreamPathTemplate": "/api/cms-kit-public/{everything}",
    "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
}

You can make different configurations for each method or endpoint for your service and add QoS configurations based on your business requirements. You can check the ocelot documentation for more.

Build Errors Typo

After adding your module completely, you should see some changes on the different pages to the injected dependencies. In ProductServiceDbContext the overridden method OnModelCreating may be a typo because of the parameter name. For example, the CmsKit comes with the builder parameter name but in this class, the parameter name is modelBuilder. It's enough to change it with the correct one.

[ConnectionStringName(ProductServiceDbProperties.ConnectionStringName)]
public class ProductServiceDbContext : AbpDbContext<ProductServiceDbContext>
{
    protected override void OnModelCreating(ModelBuilder builder)
    {
        //`builder` may be `modelBuilder`
        builder.ConfigureCmsKit();
    }
}

Implementing ICmsKitDbContext

After running the add module command, you should see your migration files under the Migrations in the EntityFrameworkCore project. If it's empty please make sure whether to implement IModuleDbContext or not. Once implemented, the compiler should warn you to import your entities here. Now, you're ready to create your migration properly by using the following command line:

dotnet ef migrations add "InitialCmsKit"

If you create your migrations properly, you just need to run the project. ABP Framework will handle it automatically.

[ConnectionStringName(ProductServiceDbProperties.ConnectionStringName)]
public class ProductServiceDbContext : AbpDbContext<ProductServiceDbContext>, ICmsKitDbContext
{
    public DbSet<Product> Products { get; set; } //It's already defined in the template project.
    public DbSet<Comment> Comments { get; set; }
    public DbSet<CmsUser> User { get; set; }
    //The other implemented entities come from ICmsKitDbContext
}

Now you should configure AbpDbContextOptions in the ProductServiceEntityFrameworkCoreModule under the EntityFrameworkCore project. You should already see the configuration for your service in the ConfigureServices method of your project, but you also need to configure it for the new module projects.

ProductServiceEntityFrameworkCoreModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        //The other congiurations
        Configure<AbpDbContextOptions>(options =>
        {
            //It comes via the microservice template
            options.Configure<ProductServiceDbContext>(c =>
            {
                c.UseSqlServer(b =>
                {
                    b.MigrationsHistoryTable("__ProductService_Migrations");
                });
            });
            //Need to add this configuration for the CmsKit implementation
            options.Configure<CmsKitDbContext>(c =>
            {
                c.UseSqlServer(b =>
                {
                    b.MigrationsHistoryTable("__ProductService_Migrations");
                });
            });
        });
    }
}

Using Component

If you would like to use the defined component in the module on your web page, you should add its related page on NuGet. After adding your package you should add the dependency to YourModulePublicWebModule as the following code:

abp add-package Volo.CmsKit.Web
using Volo.CmsKit.Public.Web;

[DependsOn(typeof(CmsKitPublicWebModule))]
public class PublicWebModule : AbpModule
{
    //Configurations
}

Now you can use the components on your page. For example it's added into Index.cshtml under PublicWeb\Pages\Products

@using @using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting

@await Component.InvokeAsync(typeof(CommentingViewComponent), 
    new {entityType = "quote", entityId = @product.Id})

Configured External User

To submit some components you need to log in to the system. You're already logged in to the system but your module database can be empty, hence you need to check IdentityService for this user.

Firstly you should add the service client to IdentityServerDataSeeder under the IdentityService.HttpApi.Host

//The other configurations
await CreateClientAsync(
    name: "SolutiontName_ProductService",
    scopes: commonScopes.Union(new[]
    {
        "IdentityService"
    }),
    grantTypes: new[] { "client_credentials" },
    secret: "1q2w3e*".Sha256(),
    permissions: new[] { IdentityPermissions.UserLookup.Default } 
);

Then change your appsetting.json by adding the following code under ProductService.HttpApi.Host

"RemoteServices": {
    "AbpIdentity": {
    "BaseUrl": "https://localhost:44388" **IdentityService Port**
    }
},
"IdentityClients": {
    "Default": {
    "GrantType": "client_credentials",
    "ClientId": "SolutiontName_ProductService",
    "ClientSecret": "1q2w3e*",
    "Authority": "https://localhost:44322", **AuthServer Port**
    "Scope": "IdentityService"
    }
}

Now add the Nuget package by using the following code and implement it to the module.

dotnet add package Volo.Abp.Identity.Pro.HttpApi.Client

dotnet add package Volo.Abp.Http.Client.IdentityModel.Web

Also, add the configuration for CmsKitCommentOptions

using Volo.CmsKit.Comments;
using Volo.Abp.Identity;
using Volo.Abp.Http.Client.IdentityModel.Web;

[DependsOn(
    typeof(AbpIdentityHttpApiClientModule),
    typeof(AbpHttpClientIdentityModelWebModule)
)]
public class ProductServiceHttpApiHostModule : AbpModule
{
    Configure<CmsKitCommentOptions>(options =>
    {
        options.EntityTypes.Add(new CommentEntityTypeDefinition("quote"));
    });
}

Finally, you need to map CmsKit to ProductService in SharedHostingModule under Shared.Hosting

public override void ConfigureServices(ServiceConfigurationContext context)
{
    Configure<AbpDbConnectionOptions>(options =>
    {
        options.Databases.Configure("ProductService", database =>
        {
            database.MappedConnections.Add("CmsKit");
            database.MappedConnections.Add("ProductService");
        });
    }
}

Note: If you meet the same problem after doing these steps, please remove your volume on Docker and repeat the same steps on IdentityService to get the changes.

If you applied all the steps correctly, you should see the below output after clicking the Send button.

first-comment

Was this page helpful?
Please make a selection.
Thank you for your valuable feedback!

Please note that although we cannot respond to feedback, our team will use your comments to improve the experience.

In this document
Mastering ABP Framework Book
Mastering ABP Framework

This book will help you gain a complete understanding of the framework and modern web application development techniques.