I need to implement AddedBy/ChangedBy type fields on my Base Entity that all other entities inherit from ( Fluent Nhibernate ).
Accessing HttpContext.User.Identity
HttpContext.Current is a static member that you can access anywhere in the application. https://msdn.microsoft.com/en-us/library/system.web.httpcontext.current%28v=vs.110%29.aspx Obviously there are problems, such as if you don't HAVE an HttpContext when the code is called.
So HttpContext.Current.User should work for you. I wouldn't recommend it, because your underlying data access code is now depending on stuff that should be kept to your display or controller logic, etc. Also, this assumes that your data access is in the web application itself and not part of, say, an external library.
Personally, I'd just pass in the salient details, like user ID and access time, as part of the add and modify database calls. Make an "AuditTrail" class or something. That would let you reuse that data access code (always a good thing) in another project without having to pull out all the HttpContext stuff.
I have used a factory to get the correct repo with or without a "CurrentUser" since sometimes you need to know who the user is and sometimes you don't.
//I have a current user that I got from the Identity
var repo = RepoFactory.GetRepo<Users>(currentUserId);
//I don't have a current user
var repo = RepoFactory.GetRepo<Users>()
This way you can pull the Identity from the HttpContext and pass only details you need to the repo.
HttpContext.User.Identity
is of System.Security.Principal.IIdentity
type. Don't mess it up with Microsoft.AspNet.Identity library (NuGet package) which is actually pointed by asp.net-identity tag in your question.
Identity lib consists of common part and its ORM implementation. Typically it is for Entity Framework. But if you're going to use Microsoft.AspNet.Identity
package in the way you describe with NHibernate, then you most likely will need this package.
I didn't use it, but I used EF implementation. See this answer how to inherit of predefined IdentityDbContext<T>
where T is your User class. I guess, NH has similar fluent configuration. Then you can link any of entities in your DbContext
to AppUser
The AddedBy/ChangedBy field is potentially important in any data backend. You may even want to have AccessedBy for logging purposes. Therefore, you would want to think that the user information is a central part of your data. It is also possible that you may want other details such as the client's IP address logged for security reasons. Probably a good idea to have the entire context rippled down to the data layer so that you have the flexibility to capture and save the client information.
Access the HttpContext from the Data Layer makes the life harder, specially if you use Unit Tests. The solution is to create a service to provide application wide user information, something like:
public interface ICurrentUserService {
string UserName {get;}
string UserId {get;}
string HostIP {get;}
// etc.
}
Then you can implement the concrete service and inject it using your preferred IoC container.
public class CurrentWebUserService : ICurrentUserService {
// implement interface members
public CurrentWebUserService(HttpContext context) { ... }
public string UserName { get { ... } }
// etc.
}
// maybe you want a stub service to inject while unit testing.
public class CurrentUserServiceStub : ICurrentUserService {
}
// data layer
public class MyDaoService {
public DaoService(ICurrentUserService currentUser) { ... }
}
You're correct. Referencing your HttpContext.User.Identity
class from within your repository is not a good idea. The HttpContext
is a UI concern and as such, should go no further than the UI layer.
What you should be doing is harnessing an IoC container (such as StructureMap) to inject your dependency (HttpContext.User.Identity
) details into your repository, or any other layer such as the service layer via dependency injection.
For an example of how this can be setup (in this instance it's the session object) see the latter part of this answer.