Activities of "enisn"

Answer

We're using MiniExcel library in ABP Suite to export data as excel whenever you generate a code by checking Enable Excel Export option.

You can use the same library to import too

public async Task ImportAsync(IRemoteStreamContent file)
{
    using var stream = file.GetStream();
    var rows = stream.Query<BookExcelDto>().ToList();

    var bookList = rows.Select(row => new Book(row.Id, row.Title, row.AuthorName)).ToList();

    await _bookRepository.InsertManyAsync(bookList);
}

You can read this article if you want to learn usage of IRemoteStreamContent and upload a file from angular: https://abp.io/community/articles/how-to-upload-and-download-files-in-the-abp-framework-using-angular-que8cdr8

Hi,

Here is my first findings:

Client Proxies is used for sending request by using AppService interfaces from Application.Contracts project they tehy should be generated in HttpApi.Client project. In case of need, you'll need to reference HttpApi.Client project of the related project.

When you generate them in the application layer, it replaces the original implementation of the interfaces.

Can you send a sample project that reproduces problem to my E-mail address with this issue number?

enis.necipoglu@volosoft.com

Answer

Hi,

Have you tried Entity Extension System for that?

https://abp.io/docs/latest/framework/architecture/modularity/extending/module-entity-extensions#create-update-forms

And also this method for singular pull cachces: https://github.com/abpframework/abp/blob/d7e0ee30031eb61a59b0745c8fe81b94d4e859ef/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs#L408

Hi,

I found where it's cached after repository is pulled: https://github.com/abpframework/abp/blob/b54f4bff04181fad94f1f27a0300eda37cfbc9f0/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs#L234

Unfortunately it's not a virtual method that you cannot easily override it but you can override the methods that call this method such as PullAsync and PullAllAsync to define caching logic on your own:

[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IDocumentAdminAppService), typeof(DocumentAdminAppService))]
public class MyDocumentAdminAppService : DocumentAdminAppService
{
    private readonly IProjectRepository _projectRepository;
    private readonly IDocumentRepository _documentRepository;
    private readonly IDocumentSourceFactory _documentStoreFactory;
    private readonly IDistributedCache<DocumentUpdateInfo> _documentUpdateCache;
    private readonly IDistributedCache<List<VersionInfo>> _versionCache;
    private readonly IDistributedCache<LanguageConfig> _languageCache;
    private readonly IDocumentFullSearch _elasticSearchService;

    public MyDocumentAdminAppService(IProjectRepository projectRepository, IDocumentRepository documentRepository, IDocumentSourceFactory documentStoreFactory, IDistributedCache<DocumentUpdateInfo> documentUpdateCache, IDistributedCache<List<VersionInfo>> versionCache, IDistributedCache<LanguageConfig> languageCache, IDocumentFullSearch elasticSearchService) : base(projectRepository, documentRepository, documentStoreFactory, documentUpdateCache, versionCache, languageCache, elasticSearchService)
    {
        this._projectRepository = projectRepository;
        this._documentRepository = documentRepository;
        this._documentStoreFactory = documentStoreFactory;
        this._documentUpdateCache = documentUpdateCache;
        this._versionCache = versionCache;
        this._languageCache = languageCache;
        this._elasticSearchService = elasticSearchService;
    }

    private async Task UpdateDocumentUpdateInfoCache(Document document)
    {
        var cacheKey = $"DocumentUpdateInfo{document.ProjectId}#{document.Name}#{document.LanguageCode}#{document.Version}";
        await _documentUpdateCache.SetAsync(cacheKey, new DocumentUpdateInfo
        {
            Name = document.Name,
            CreationTime = document.CreationTime,
            LastUpdatedTime = document.LastUpdatedTime
        },

        // 👇 Define your cache options here
        new DistributedCacheEntryOptions
        {
            AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30),
            SlidingExpiration = TimeSpan.FromMinutes(10)
        });
    }

    /*
     * ====================
     * OVERRIDE OTHER METHODS WITH ORIGINAL LOGIC BELOW
     * THAT ENSURES THEY CALLS THE METHOD WE WROTE ABOVE
     * ====================
     */

    public override async Task PullAsync(PullDocumentInput input)
    {
        var project = await _projectRepository.GetAsync(input.ProjectId);

        var source = _documentStoreFactory.Create(project.DocumentStoreType);
        var sourceDocument = await source.GetDocumentAsync(project, input.Name, input.LanguageCode, input.Version);

        await _documentRepository.DeleteAsync(sourceDocument.ProjectId, sourceDocument.Name,
            sourceDocument.LanguageCode, sourceDocument.Version);
        await _documentRepository.InsertAsync(sourceDocument, true);
        await UpdateDocumentUpdateInfoCache(sourceDocument);
    }

    public override async Task PullAllAsync(PullAllDocumentInput input)
    {
        var project = await _projectRepository.GetAsync(input.ProjectId);

        var navigationDocument = await GetDocumentAsync(
            project,
            project.NavigationDocumentName,
            input.LanguageCode,
            input.Version
        );

        if (!DocsJsonSerializerHelper.TryDeserialize<NavigationNode>(navigationDocument.Content, out var navigation))
        {
            throw new UserFriendlyException($"Cannot validate navigation file '{project.NavigationDocumentName}' for the project {project.Name}.");
        }

        var leafs = navigation.Items.GetAllNodes(x => x.Items)
            .Where(x => x.IsLeaf && !x.Path.IsNullOrWhiteSpace())
            .ToList();

        var source = _documentStoreFactory.Create(project.DocumentStoreType);

        var documents = new List<Document>();
        foreach (var leaf in leafs)
        {
            if (leaf.Path.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
                leaf.Path.StartsWith("https://", StringComparison.OrdinalIgnoreCase) ||
                (leaf.Path.StartsWith("{{") && leaf.Path.EndsWith("}}")))
            {
                continue;
            }

            try
            {
                var sourceDocument = await source.GetDocumentAsync(project, leaf.Path, input.LanguageCode, input.Version);
                documents.Add(sourceDocument);
            }
            catch (Exception e)
            {
                Logger.LogException(e);
            }
        }

        foreach (var document in documents)
        {
            await _documentRepository.DeleteAsync(document.ProjectId, document.Name,
                document.LanguageCode,
                document.Version);

            await _documentRepository.InsertAsync(document, true);
            await UpdateDocumentUpdateInfoCache(document);
        }
    }

    private async Task<Document> GetDocumentAsync(
            Project project,
            string documentName,
            string languageCode,
            string version)
    {
        version = string.IsNullOrWhiteSpace(version) ? project.LatestVersionBranchName : version;
        var source = _documentStoreFactory.Create(project.DocumentStoreType);
        var document = await source.GetDocumentAsync(project, documentName, languageCode, version);
        return document;
    }
}

It seems this module is not easily extended, I'll create an issue to the team to configure / customize it easily

Hi,

It seems it targets one single framework at the moment: https://github.com/abpframework/abp/blob/e9412912c6e4ec5ae1d26f9c4d83110390e5388d/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj#L7

There might be transition version or temporary package, in the source code of that package, it seems it targets the .NET9.

I'm refunding your ticket since the problem is on our side

Answer

You can still use Static Client Proxies in your existing project to prevent package dependencies with.Contracts packages. This dependency easily can be eliminated

Hi, we tried updating to v9.1.3 and the issue is still there. Worth mentioning that this happens only on reload, navigating to different pages back and forth works fine.

Any other suggestions on what we can try? Thanks.

Can you try to delete all node_modules folder and yarn.lock/package.lock files. Try to install dependencies from scratch again executing yarn command. If the problem still exists, I'll deliver this issue to the @angular team asap

Answer

Hi,

In the screenshot it seems you're using old microservice template. In the new template most of the problems are resolved. Can you try creating a new Microservice Template by using ABP Studio and check how it works. You may slowly migrate to the new pattern

Showing 61 to 70 of 779 entries
Boost Your Development
ABP Live Training
Packages
See Trainings
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 October 30, 2025, 06:33