I'm creating a multi-tenant ASP.NET application using NHibernate (shared schema). I had intended to use NHibernates Event Listeners to inspect/modify entities prior to saving to ensure that the current tenants ID was being saved against the entity.
The authentication token containing the tenant ID is managed higher up and passed down into the data layer.
My problem is that Event Listeners are configured against an NHibernate Configuration rather than a specific ISession. This means that there's no way to pass in any identifiers for it to use, although I can access the ISession that caused the event to fire.
How can I go about passing ISession specific data into the Event Listener?
You might be able to do this with an IInterceptor implementation because ISessionFactory has an overloaded OpenSession method that accepts an IInterceptor. Usage would be something like:
var interceptor = new MyInterceptor(tenantId);
var session = factory.OpenSession(interceptor);
Unfortunately there's no overload that accepts listeners.
Related
I have an Event Listener that finds an entity object in the database an checks whether current user is authorized for it. I need this object further in Controller, so my question is: what is the best way to pass an object from Event listener to Controller?
I have several options, but none of them is good enough.
In Controller, using repository to fetch the same object from database second time - which is actually less coupled but produces additional DB query.
Serializing object in Event Listener and passing it to Controller in request.
Making a service that will set() object in Event Listener and get() in Controller - but it looks like architectural flaw to assign service for such purposes.
Maybe anyone has better solution?
An Event Listener is a service like any other service. You can save your object to a protected member of your service, create a getter for it and in the controller get this service and retrieve the objet using the getter
At some point in the life cycle of an authenticated ASP.NET request the IdentityUser is retrieved from the backing store (either Entity Framework or otherwise). I'd like to hook into that process. The reason is that the user has some collection properties and I'd like to retrieve those as well with one call to the database (using IQueryable<T>.Include).
Is this possible in ASP.NET identity?
I think you probably want to implement a ClaimsAuthenticationManager
The claims authentication manager provides a place in the claims processing pipeline for applying processing logic (filtering, validation, extension) to the claims collection in the incoming principal before execution reaches your application code.
Since what you're looking for sounds like extension to me. You override the Authenticate method that has this signature:
public virtual ClaimsPrincipal Authenticate(
string resourceName,
ClaimsPrincipal incomingPrincipal
)
You probably want to override UserStore and override all of the FindXXX methods that return a User do add whatever Includes that you wanted.
I've been thinking of how I could use one instance of a DbContext per HttpRequest in a layered application. One of the solutions I came up with would be to create an HttpModule that would initialize an instance of the context in HttpContext.Current.Items in the BeginRequest event handler and then dispose it in the EndRequest event handler.
The approach above poses a problem though: I need to reference System.Web in my data layer and business layer in order to get a hold of the stored DbContext instance. This is probably okay but I prefer to avoid going that route. What if I wanted to reference and use my data layer and business layers from a non-web application?
Any ideas?
You can use dependency injection. Simply create interface IContextHolder with method to get a context and inject the instance into your lower layer from the web application. The implementation of this interface will be different for different types of applications - it will wrap the access to the real storage for your context instance.
One of the simplest solutions would be to wrap the access to the data context in a static property in a facade/gateway class.
This way, in a web application, the property could access the HttpContext.Current.Items and store the context there. On the other hand, if the http context is missing, you could implement any other lifetime management policy for a non-web application.
public static TheDbContext Current {
get {
if ( HttpContext.Current != null ) {
// lifetime management for a web app
// e.g. with the Items container
}
else {
// lifetime management for a non-web app
}
}
}
The facade itself doesn't have to be a part of the data layer, you don't then reference System.Web in a data layer.
UserList userList = (UserList) Component.getInstance(UserList.class);
return userList.getUserByLoginId(loginId);
A sample code usage of fetching a user by login id is given below. I instantiate the UserList class to call the method. What ScopeType should I use here specifically so that the object's scope is minimal.
If you want to access authenticated users via your UserList object you must keep it in application scope. But, it is alive during the entire application life. So, it is not minimal.
Another approach may store logged-in users in a database table and you can query this table via an event scoped component. Event scope is equivalent of Http's "request" scope. So, it is killed after each server request.
I have a login.java servlet and, as its name says, it provides login facilities to my web application.
I'm a newbie and I'm using EJB 3.1 and EE 6. In my LoginBean.java EBJ I have a no-arguments constructor and another one that has some parameters (email, password, etc).
At certain point in the servlet code I have the calling to instantiate my EJB:
#EJB LoginBean loginBean;
I'd like to know if it's possible (and how) to call the other constructor instead of the zero-arguments one.
Thanks a lot.
Cheers.
You don't want to do that. The one and same servlet is shared among all users, so the EJB is also shared among all users. You don't want to store user-specific data as instance variable of the servlet or EJB class. It would be shared among all webpage visitors.
Rather move the arguments to a EJB method which you invoke in the doPost() method of the login servlet.
User user = loginBean.login(username, password);
and then store this in the HTTP session when it went successful
request.getSession().setAttribute("user", user);
so that the rest of your webapp can intercept on this to determine if the user is logged in or not.
if (request.getSession().getAttribute("user") != null) {
// User is logged in.
} else {
// User is not logged in.
}
I 100% agree with BalusC. In addition to his answer I would like to add that you normally* never explicitly reference the constructor of an EJB bean, even if doing so would theoretically make sense (e.g. when passing in some dependencies, or some configuration parameter).
EJB beans are managed objects and what you are getting in your #EJB annotated field is not the actual object but a stub (proxy). The actual object instance to which the stub points is most likely constructed long before you get this stub to it and also very likely comes from a pool.
(*)Some kind of units tests may be an exception to this rule.