brockallen / BrockAllen.MembershipReboot

MembershipReboot is a user identity management and authentication library.
Other
742 stars 238 forks source link

How to set values from HttpContext when doing BulkUpload #636

Closed parkinsona closed 7 years ago

parkinsona commented 8 years ago

Hi,

I have implemented some custom EventHandlers that log certain information to the DB using this function:

 public void AddAuditEntry(UserAccountEvent<CustomUser> evt, string additionalDetail = null)
        {

            using (var db = new CustomMembershipRebootDatabase())
            {

                var audit = new AuditTrail
                {

                    Date = DateTime.UtcNow,
                    Activity = GetTypeNameWithoutGenericArity(evt),
                    Detail = additionalDetail,
                    ClientIP = HttpContext.Current.Request.UserHostAddress,
                    Username = evt.Account.Username,
                    Browser = HttpContext.Current.Request.Browser.Browser,
                    UserAgent = HttpContext.Current.Request.UserAgent,
                    Source = Constants.ApplicationName,                    
                    UpdatedBy = GetUpdatedBy(evt)
                };
                db.Audits.Add(audit);
                db.SaveChanges();
            }
        }

This works great from all my synchronous calls in my site. However, when I introduced this new logging functionality, it breaks my BulkUserUpload. My bulkuser upload loads a file from the html file and processes it in its own Task so that it can return a result to the user right away. It then emails the user upon completion.

Task.Run(() => bulkDS.ParseCSVFile(model.File.FileName, csvStreamReader, client, app, emails,  model.SendWelcomeEmail));

Because the task runs in its own thread, it doesn't have access to the HttpContext because it is null. I know I could pass the values of UserHostAddress, Browser, UserAgent etc, through my Task.Run, but I don't know how I could get them to be used by my event handler.

All I am wanting to do, is have the user get a response back ASAP after they submit their file to let them know it has been received and is being processed. I don't want them to have to wait until its completed.

Do you have any suggestions on how I could rework things to allow this to work?

brockallen commented 8 years ago

Yea, you're going to have to copy those values. Or pass the context... but not sure what sort of trouble that might get you into.

parkinsona commented 8 years ago

So I'm thinking the best way to pass these through would be updating the eventHandler and updating my config like so:

  Config.AddEventHandler(new AuditEventHandler(HttpContext.Current.User as ClaimsPrincipal)); 

This would be ok, but I'm using a static MembershipRebootConfiguration as per the samples in the Customizations Sample. Does the MembershipRebootConfiguration have to be static? Will there be any odd effects if its non-static?

My other thought, is that I could remove the Task.Run from my controller action and make the call synchronous. Then in the View, I would call it using Ajax, instead of a full post back. This might give me the desired result. The only concern here, is if the user navigates away from the page, the ajax response won't be received. This is ok from a user perspective because they'll be sent an email on completion of the process.