Activities of "maliming"

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

hi

The RequireFeatures method of ApplicationMenuItem requires the feature that is ToggleStringValueType

Your features both are FreeTextStringValueType

Showing 2141 to 2150 of 11567 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.