Open Closed

Extending Entities - EntityChanges AuditLog #6597


User avatar
0
thanhlg created

Check the docs before asking a question: How to use extended field query in EF query?, [Filter User list by new extra property #784](https://support.abp.io/QA/Questions/784/Filter-User-list-by-new-extra-property), How to add custom property to the user entity,Module Entity Extensions | Documentation Center | ABP.IO ...

  • ABP Framework version: v8.0.2
  • UI Type: Blazor WASM / Blazor Server
  • Database System: EF Core (PostgreSQL)

Hi Support Teams,

I have two questions:

  1. Is there a way to use ScreenUrl within ExtraProperties instead of creating an additional ScreenUrl column and using EF.Property(u, "ScreenUrl") to write the query statement?

Below is my code.

2. How can I add `context.GetHttpContext().Request.Headers["screen-url"]` to the `ScreenUrl` column in `EntityChanges`? Currently, when I run it, it only adds it to the `ScreenUrl` in `ExtraProperties` but doesn't save it to the newly added `ScreenUrl` column.

public class ExtendedAuditLogContributor : AuditLogContributor
{
    public override void PreContribute(AuditLogContributionContext context)
    {  
        context.AuditInfo.SetProperty(
        "ScreenUrl",
            context.GetHttpContext().Request.Headers["screen-url"]
        );

    }

    public override void PostContribute(AuditLogContributionContext context)
    {
        var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>();
         
        foreach (var change in context.AuditInfo.EntityChanges)
        {
            change.SetProperty(
            "ScreenUrl",
            context.GetHttpContext().Request.Headers["screen-url"]);

            change.SetProperty(
            "UserId", currentUser.Id); 
        }
    }
}


21 Answer(s)
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    Is there a way to use ScreenUrl within ExtraProperties instead of creating an additional ScreenUrl column and using EF.Property(u, "ScreenUrl") to write the query statement?

    Unfortunately no, It will be calculated on the client side instead of the server client, which will affect query performance: https://learn.microsoft.com/en-us/ef/core/querying/client-eval

    How can I add context.GetHttpContext().Request.Headers["screen-url"] to the ScreenUrl column in EntityChanges? Currently, when I run it, it only adds it to the ScreenUrl in ExtraProperties but doesn't save it to the newly added ScreenUrl column.

    Could you share a simple minimal project to reproduce the problem? I will check it, thanks. my email is shiwei.liang@volosoft.com

  • User Avatar
    0
    thanhlg created

    Hi liangshiwei,

    I have sent you an email, please check and assist me. Thanks.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    Sorry, but I can't download the project.

  • User Avatar
    0
    thanhlg created

    Sorry, I have sent you a new email. Please check it again.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    I can download it. But the project looks like an empty project .

  • User Avatar
    0
    thanhlg created

    It seems that the project screenshot you sent is not mine. I have tried downloading and checking it. This is my project.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    I made some changes to the project and it works for me.

    I have shared the project with you via email, you can check it

    Steps

    • Run dotnet ef database update to create database. (for authserver and httpapihost)
    • Run the AuthServer, HttpApi.Host and Blazor project
    • Login and navigate to common page
    • Click the Create test button
  • User Avatar
    0
    thanhlg created

    It worked. Thank you very much.

    But I'm still facing an issue. Currently, in Blazor WebAssembly, I have code in HttpApi.Client.

    and I use context.GetHttpContext().Request.Headers["screen-url"].ToString(); to get the URL.

    However, using this approach won't work in Blazor Server. Is there any way to retrieve the URL when using Blazor Server?

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Is the Blazor server a tiered solution?

  • User Avatar
    0
    thanhlg created

    Is the Blazor server a tiered solution?

    Yes, that's correct.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    I think it should be working.

    How I reproduce the problem? I will check it.

  • User Avatar
    0
    thanhlg created

    Here is the result when running Blazor WebAssembly. When I run Blazor Server, I am unable to find the Screen-Url, and there is no data for Screen-Url being saved in the AuditLogs and EntityChange database tables.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    You can try:

    public class MyHubFilter : IHubFilter
    {
        public ValueTask<object?> InvokeMethodAsync(HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object?>> next)
        {
            var httpContext = invocationContext.Context.GetHttpContext();
            if (httpContext != null)
            {
                var navigationManager = invocationContext.ServiceProvider.GetRequiredService<NavigationManager>();
                httpContext.Request.Headers["screen-url"] = navigationManager.Uri;
            }
            
            return next(invocationContext);
        }
    }
    
    
     public override void PreConfigureServices(ServiceConfigurationContext context)
     {
        Configure<HubOptions>(options =>
        {
            options.AddFilter<MyHubFilter>();
        });
    }
    
  • User Avatar
    0
    thanhlg created

    When I add the code you provided into HttpApi like this: Then, when I run project, I encounter this error:

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Please add to the Blazor server instead of HttpAPI project

  • User Avatar
    0
    thanhlg created

    I'm still unable to retrieve the Screen-url when using Blazor Server. :(

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Can you share a project?

  • User Avatar
    0
    thanhlg created

    Can you share a project?

    Sure, I have created a new project, and I have sent it to your email.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    You did not configure the AuditMessageHandler

    public override void PreConfigureServices(ServiceConfigurationContext context)
    {
        PreConfigure<AbpHttpClientBuilderOptions>(options =>
        {
            options.ProxyClientBuildActions.Add((remoteServiceName, clientBuilder) =>
            {
                clientBuilder.AddHttpMessageHandler<AuditMessageHandler>();
            });
        });
    }
    
  • User Avatar
    0
    thanhlg created

    I apologize for the delayed response. Do I need to make any modifications to the AuditMessageHandler?

    Because when I configure the AuditMessageHandler, I encounter an error when running it:

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    Yes you need to make some changes

    Idea from: https://stackoverflow.com/questions/77129117/blazor-navigationmanager-not-initialized-error

    Add AppInfo class to Blazor server project.

    public class AppInfo : ISingletonDependency
    {
        public string? CurrentUrl { get; private set; }
    
        public void UpdateAppUrl(string url)
        {
            this.CurrentUrl = url;
        }
    }
    

    Move AuditMessageHandler class to Blazor Server project

    public class AuditMessageHandler : DelegatingHandler, ITransientDependency
    {
        private readonly AppInfo _appInfo;
    
        public AuditMessageHandler(AppInfo appInfo)
        {
            _appInfo = appInfo;
        }
    
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            request.Headers.Add("screen-url", _appInfo.CurrentUrl);
    
            return base.SendAsync(request, cancellationToken);
        }
    }
    

    Add AppInfoProvider.razor to Blazor server project.

    @code {
    
        [Inject] private NavigationManager NavigationManager { get; set; } = default!;
        [Inject] private AppInfo AppInfo { get; set; } = default!;
    
        protected override void OnInitialized()
        {
            NavigationManager.LocationChanged += (sender, args) =>
            {
                this.AppInfo.UpdateAppUrl(this.NavigationManager.Uri);
            };
        }
    }
    
    -------------------
    Configure<AbpLayoutHookOptions>(options =>
    {
        options.Add(LayoutHooks.Body.First, typeof(AppInfoProvider),StandardLayouts.Application);
    });
    
Made with ❤️ on ABP v9.1.0-preview. Updated on December 12, 2024, 07:15