Activities of "maliming"

Check the full logs see:

If the redis was cleared, the log will show Creating key for every deployment.

[INF] Creating key {12da01ce-7e32-43e6-bc76-3bb8a969cccc} with creation date 2025-05-16 01:14:05Z, activation date 2025-05-16 01:14:05Z, and expiration date 2025-08-14 01:14:05Z.
[WRN] No XML encryptor configured. Key {12da01ce-7e32-43e6-bc76-3bb8a969cccc} may be persisted to storage in unencrypted form.

hi

For each deployment Redis container would be cleared or not?

You can check your deployment setting.

Is your Redis running in a container or on a physical machine?

Thanks.

sure

ok.thanks

hi

Add a AddTenantToRouteclass then add it to aspnet core system.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Routing;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.MultiTenancy;

namespace MyCompanyName.MyProjectName.Web;

public class AddTenantToRoute : IPageRouteModelConvention, IApplicationModelConvention
{
    public void Apply(PageRouteModel model)
    {
        var selectorCount = model.Selectors.Count;
        var selectorModels = new List<SelectorModel>();
        for (var i = 0; i < selectorCount; i++)
        {
            var selector = model.Selectors[i];
            selectorModels.Add(new SelectorModel
            {
                AttributeRouteModel = new AttributeRouteModel
                {
                    Template = AttributeRouteModel.CombineTemplates("{__tenant:regex(^[a-zA-Z0-9]+$)}", selector.AttributeRouteModel!.Template!.RemovePreFix("/"))
                }
            });
        }
        foreach (var selectorModel in selectorModels)
        {
            model.Selectors.Add(selectorModel);
        }
    }

    public void Apply(ApplicationModel application)
    {
        var controllers = application.Controllers;
        foreach (var controller in controllers)
        {
            var selector = controller.Selectors.FirstOrDefault();
            if (selector == null || selector.AttributeRouteModel == null)
            {
                controller.Selectors.Add(new SelectorModel
                {
                    AttributeRouteModel = new AttributeRouteModel
                    {
                        Template = AttributeRouteModel.CombineTemplates("{__tenant:regex(^[[a-zA-Z0-9]]+$)}", controller.ControllerName)
                    }
                });
                controller.Selectors.Add(new SelectorModel
                {
                    AttributeRouteModel = new AttributeRouteModel
                    {
                        Template = controller.ControllerName
                    }
                });
            }
            else
            {
                var template = selector.AttributeRouteModel?.Template;
                template = template.IsNullOrWhiteSpace() ? "{__tenant:regex(^[[a-zA-Z0-9]]+$)}" : AttributeRouteModel.CombineTemplates("{__tenant:regex(^[[a-zA-Z0-9]]+$)}", template.RemovePreFix("/"));
                controller.Selectors.Add(new SelectorModel
                {
                    AttributeRouteModel = new AttributeRouteModel
                    {
                        Template = template
                    }
                });
            }
        }
    }
}

public class MyRouteTenantResolveContributor : RouteTenantResolveContributor
{
    public const string ContributorName = "MyRoute";

    public override string Name => ContributorName;

    protected override Task<string?> GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext)
    {
        var tenantId = httpContext.GetRouteValue(context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey) ?? httpContext.Request.PathBase.ToString();
        var tenantIdStr = tenantId?.ToString()?.RemovePreFix("/");
        return Task.FromResult(!tenantIdStr.IsNullOrWhiteSpace() ? Convert.ToString(tenantIdStr) : null);
    }
}

public override void ConfigureServices(ServiceConfigurationContext context)
{
    //...
    
    PostConfigure<RazorPagesOptions>(options =>
    {
        options.Conventions.Add(new AddTenantToRoute());
    });

    PostConfigure<MvcOptions>(options =>
    {
        options.Conventions.Add(new AddTenantToRoute());
    });
    
    context.Services.ConfigureApplicationCookie(x =>
    {
        x.Cookie.Path = "/";
    });

    Configure<AbpTenantResolveOptions>(options =>
    {
        options.TenantResolvers.Add(new MyRouteTenantResolveContributor());
    });
    //...
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
    //...
    app.Use(async (httpContext, next) =>
    {
        var tenantMatch = Regex.Match(httpContext.Request.Path, "^/([^/.]+)(?:/.*)?$");
        if (tenantMatch.Groups.Count > 1 && !string.IsNullOrEmpty(tenantMatch.Groups[1].Value))
        {
            var tenantName = tenantMatch.Groups[1].Value;
            if (!tenantName.IsNullOrWhiteSpace())
            {
                var tenantStore = httpContext.RequestServices.GetRequiredService<ITenantStore>();
                var tenantNormalizer = httpContext.RequestServices.GetRequiredService<ITenantNormalizer>();
                var tenantInfo = await tenantStore.FindAsync(tenantNormalizer.NormalizeName(tenantName)!);
                if (tenantInfo != null)
                {
                    if (httpContext.Request.Path.StartsWithSegments(new PathString(tenantName.EnsureStartsWith('/')), out var matchedPath, out var remainingPath))
                    {
                        var originalPath = httpContext.Request.Path;
                        var originalPathBase = httpContext.Request.PathBase;
                        httpContext.Request.Path = remainingPath;
                        httpContext.Request.PathBase = originalPathBase.Add(matchedPath);
                        try
                        {
                            await next(httpContext);
                        }
                        finally
                        {
                            httpContext.Request.Path = originalPath;
                            httpContext.Request.PathBase = originalPathBase;
                        }
                        return;
                    }
                }
            }
        }

        await next(httpContext);
    });
    app.UseRouting();
    app.MapAbpStaticAssets();

    //...

: )

hi

I will find a way.

is therefore the first one to be called.

Add it to the last position.

Configure<AbpFeatureOptions>(options =>
{
    options.ValueProviders.Add<FvpRoleBasedFeatureValueProvider>();
});

hi

What is the final URL format you expect?

Like this? https://localhost:44303/tenantname/api/abp

hi

Configure<AbpFeatureOptions>(options =>
{
    options.ValueProviders.Insert(0, typeof(FvpRoleBasedFeatureValueProvider));
});

The valueProviders order is

DefaultValueFeatureValueProvider
EditionFeatureValueProvider
TenantFeatureValueProvider

Your FvpRoleBasedFeatureValueProvider should be added after DefaultValueFeatureValueProvider,

eg:

DefaultValueFeatureValueProvider

FvpRoleBasedFeatureValueProvider

EditionFeatureValueProvider
TenantFeatureValueProvider

But this depends on your business logic. You can add before TenantFeatureValueProvider.

eg:

DefaultValueFeatureValueProvider
EditionFeatureValueProvider
TenantFeatureValueProviderr

FvpRoleBasedFeatureValueProvider
Showing 2141 to 2150 of 11568 entries
Learn More, Pay Less
33% OFF
All Trainings!
Get Your Deal
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.1.0-preview. Updated on December 25, 2025, 06:16
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.