Base solution for your next web application
Open Closed

LastModifierUserId is not updating and remains NULL. #12354


User avatar
0
TimMackey created

I'm using ASP.NET Core + Angular version 8.31

I have a table defined as follows: (inconsequential code omitted)

using Microsoft.EntityFrameworkCore;

namespace ExamDbContextLibrary
{
    public class ExamDbContext : DbContext
    {
        public virtual DbSet JobStatuses { get; set; }

        public ExamDbContext(DbContextOptions options)
           : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
        }
    }
}

...and...

using System;
using System.ComponentModel.DataAnnotations.Schema;

namespace ExamDbContextLibrary
{
    [Table("TtmJobStatuses")]
    [Audited]
    public class JobStatus : AuditedEntity
    {
        //=========================================================================================
        #region Constructor
        //-----------------------------------------------------------------------------------------
        public JobStatus()
        {
            TimeZoneInfo pstZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
            CreationTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, pstZone);
        }
        //-----------------------------------------------------------------------------------------
        #endregion
        //=========================================================================================
        #region Mapped Properties
        //-----------------------------------------------------------------------------------------
        public string ItemGuid { get; set; }
        //-----------------------------------------------------------------------------------------
        #endregion
        //=========================================================================================
        #region NotMapped Methods
        //-----------------------------------------------------------------------------------------
        public void UpdateLastModifier(long? userId)
        {
            LastModifierUserId = userId;
            TimeZoneInfo pstZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
            LastModificationTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, pstZone);
        }
        //-----------------------------------------------------------------------------------------
        #endregion
        //=========================================================================================
    }
}

I invoke the job as follows (inconsequential code omitted):

IJobManagerService _jobManagerService;

public MyAppService(IJobManagerService jobManagerService)
{
    _jobManagerService = jobManagerService;
}
//-----------------------------------------------------------------------------------------
[HttpPost]
[AbpAuthorize(AppPermissions.Pages_Exams_Edit)]
public async Task MyTask()
{
    await _jobManagerService.ExecuteJob(somejobArgs);
}

...and execute the job, and update LastModifierUserId as follows:

usings ...
using DbContext = ngTTM.EntityFrameworkCore.ngTTMDbContext;

namespace ngTTM.TtmJobManager
{
    [AbpAuthorize(AppPermissions.Pages_Exams)]
    public class JobManagerService : ngTTMAppServiceBase, IJobManagerService
    {
        private readonly IBackgroundJobManager _backgroundJobManager;
        private readonly ISettingManager _settingManager;
        private readonly IAbpSession _abpSession;
        private readonly IWebHostEnvironment _webHostEnvironment;
        //-----------------------------------------------------------------------------------------
        static JobManagerService()
        {
        }
        //-----------------------------------------------------------------------------------------
        public JobManagerService(
            IAbpSession abpSession,
            IWebHostEnvironment webHostEnvironment,
            ISettingManager settingManager,
            IBackgroundJobManager backgroundJobManager
        )
        {
            _webHostEnvironment = webHostEnvironment;
            _backgroundJobManager = backgroundJobManager;
            _settingManager = settingManager;
            _abpSession = abpSession;
        }
        //-----------------------------------------------------------------------------------------
        public async Task ExecuteJob(JobArgs jobArgs)
        {
            ServiceStatusDto servicestatus = new ServiceStatusDto(L("Exams"), L("Success"));

            try
            {
                using (DbContext context = new DbContext(new DbContextOptionsBuilder()
                    .UseSqlServer(jobArgs.connectionString, options => options.EnableRetryOnFailure(3)).Options))
                {
                    JobStatus _jobStatus = context.JobStatuses.FirstOrDefault(s => s.Id == jobArgs.jobStatusId);

                    _jobStatus.UpdateLastModifier(13);
                    context.JobStatuses.Update(_jobStatus);
                    context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                ex.LogException(jobArgs.userId);
                servicestatus.success = false;
                servicestatus.failureReason = ex.Message;
            }
            return servicestatus;
        }
    }
}

LastModifierUserId value remains NULL, instead of the desired value (in this case 13).

image.png

I'm not using Abp-supplied interfaces (like IRepository<JobStatus, int>) because of the caching overhead performance penalty.
In the (few) instances where I do use the Abp interface, LastModifierUserId is correctly updated.
There are no issues updating any columns in any tables, except for LastModifierUserId when using DbContext.
What do I need to do to update LastModifierUserId in this scenario?


3 Answer(s)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @TimMackey

    The LastModifierUserId value automatically gets the user information in AbpSession. If you want to assign this value manually, you can disable the LastModifierUserId value assignment in the AuditedEntity behavior. You can disable this automatic assignment process using the DisableAuditing method below. Can you try it this way? Related Document

    using (_unitOfWorkManager.Current.DisableAuditing(AbpAuditFields.LastModifierUserId))
    {
        // LastModifierUserId will not be set by ASP.NET Boilerplate automatically
    }
    
  • User Avatar
    0
    TimMackey created

    The code is run as a background job:

    using Abp.Application.Services;
    using Abp.BackgroundJobs;
    using Abp.Dependency;
    using Abp.Domain.Uow;
    using Abp.Runtime.Session;
    using CommonLibrary;
    using DrawImagesLibrary;
    using ExceptionsLibrary;
    using FormsModelLibrary;
    using ExamJobsLibrary;
    using System;
    
    namespace ngTTM.TtmJobManager
    {
        //-----------------------------------------------------------------------------------------
        public class ExecuteAbpBackgroundJob : BackgroundJob, ITransientDependency, IApplicationService
        {
            //=========================================================================================
            #region Private Fields
            //-----------------------------------------------------------------------------------------
            private readonly IAbpSession _abpSession;
            private readonly IUnitOfWorkManager _unitOfWorkManager;
            //-----------------------------------------------------------------------------------------
            #endregion Private Fields
            //=========================================================================================
            //-----------------------------------------------------------------------------------------
            public ExecuteAbpBackgroundJob(
                IAbpSession abpSession,
                IUnitOfWorkManager unitOfWorkManager
            )
            {
                _abpSession = abpSession;
                _unitOfWorkManager = unitOfWorkManager;
            }
            //----------------------------------------------------------------------------------------
            [UnitOfWork]
            public override void Execute(JobArgs jobArgs)
            {
                try
                {
                    ExamPageLayout examPageLayout = new ExamPageLayout();
                    ExamPageData examPageData = new ExamPageData(examPageLayout);
                    DrawImages drawImages = new DrawImages(examPageLayout);
                    LocalizedStrings.Set_Localized_Strings(jobArgs.jsonL7DStrings);
    
                    using (_unitOfWorkManager.Current.DisableAuditing(AbpAuditFields.LastModifierUserId))
                    {
                        using (CurrentUnitOfWork.SetTenantId(jobArgs.tenantId))
                        {
                            using (_abpSession.Use(jobArgs.tenantId, jobArgs.userId))
                            {
                                ExecuteJobOp execJob = new ExecuteJobOp(jobArgs,
                                                                        drawImages,
                                                                        examPageLayout,
                                                                        examPageData);
                                bool success =
                                execJob.Execute_Job(jobArgs.jobStatusId);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    ex.LogException(jobArgs.userId);
                }
            }
            //-----------------------------------------------------------------------------------------
        }
    }
    

    The interface doesn't support DisableAuditing nor AbpAuditFields.
    image.png
    I'm using Abp version 5.3.0

  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @TimMackey

    This means that this DisableAuditing interface will not be used. You are already using this with job execute. When updating the JobStatus entity, you need to override the value given to LastModifierUserId automatically by Abp. You will do this with DisableAuditing. After overriding this, you need to manually assign the value yourself. If you want to assign the user in AbpSession, you can do this in the general place where you update the entity.

    You can try this sample code.

    Example Code

    _jobStatus.UpdateLastModifier(13);
    context.Entry(_jobStatus).Property(x => x.LastModifierUserId).IsModified = true;
    context.SaveChanges();
    

    If these fixes do not solve your problem, you can send your project to support@aspnetzero.com so that we can give you a more specific answer.