4

I have built a web application that is structured in a n-layer architecture, i.e. UI, BLL, API (WebAPI), DAL. What I would like to achieve with this separation of concern is to enable basic auditing on the DAL, i.e. RowCreatedBy, RowUpdatedBy and so forth, however I want to find out what is the best way to pass the user identity from the UI layer down to my Data Access Layer without adding it as a parameter on all my crud calls. The option that is there is using Thread.CurrentPrincipal, however it could work,but the catch is my application is hosted in IIS under an apppool with a specific identity set. I would like the CurrentUser to be available throughout all my application layer. Please advise the best approach?

NB: I know people may have asked this, but from the other references I have seen, none satisfy my scenario.

Donny
  • 4,738
  • 8
  • 35
  • 50

2 Answers2

0

I can't say that my approach is the "best" but it was appropriate for me.

In my case, an MVC 5 web application uses Microsoft's Identity for authentication. I use three databases to separate concerns,

  • Identity (Authentication and Authorisation)
  • Application (all application data)
  • Elmah (Exception recording)

When a record is stored in the Application database that is attributable to a user, the userId (nvarchar(128) Guid string from the Identity database) is used.

The only downside to this is, when retrieving records to display at the client, the associated names for each user id have to be added to the display data. This is quite simple as my MVC controllers pass in the ApplicationUserManager by direct injection.

In an Entity Framework model that requires the user name, I add a partial class with a name field and update it (as below). If I am using a View Model then the same approach is taken.

r.WhoSavedName = (from u in _userManager.Users where u.Id == r.WhoSavedId select u.UserName).FirstOrDefault();
pixelda
  • 1,638
  • 17
  • 16
0

One way to approach this would be to inject a class into your logic/data layers that allows access to the currently logged in user, e.g.

Declared (probably at the data layer):

interface ICurrentUserService {
     Guid GetCurrentUserId();
}

And then an implementation of this in the web layer:

class CurrentUserService : ICurrentUserService {
    public Guid GetCurrentUserId() {
        return <<User ID obtained via asp.net identity>>
    }
}

If this object is injected into your data layer classes, you should then be able to call to get the current user id without being tied to where this is actually being obtained from (i.e. no dependency on the System.Web classes).

Paddy
  • 31,468
  • 14
  • 75
  • 108